1
0
mirror of https://github.com/Interlisp/maiko.git synced 2026-01-18 09:02:39 +00:00
Nick Briggs d91de66322 Correct -Wformat-pedantic warnings
Many of the warnings were newly visible after the DBPRINT macro
was modified, but the pedantic warnings also caught existing printf
family usage which was not strictly correct.

Mostly replacing 0x%x with %p for pointers, adding (void *) for
those and other pointers, %td for ptrdiff_t, but also changing
some function parameters from UNSIGNED (uintptr_t) to int
where that was the more appropriate type.
2022-08-11 15:38:07 -07:00

642 lines
13 KiB
C

/* $Id: dlpi.c,v 1.3 2001/12/24 01:09:00 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */
#include "os.h"
#ifdef USE_DLPI
/*
* dpli.c - routines for messing with the Data Link Provider Interface.
*
* The code in this module is based in large part (especially the dl*
* routines) on the example code provided with the document "How to Use
* DLPI", by Neal Nuckolls of Sun Internet Engineering. Gotta give credit
* where credit is due. If it weren't for Neal's excellent document,
* this module just plain wouldn't exist.
*
* David A. Curry
* Purdue University
* Engineering Computer Network
* 1285 Electrical Engineering Building
* West Lafayette, IN 47907-1285
* davy@ecn.purdue.edu
*
* $Log: dlpi.c,v $
* Revision 1.3 2001/12/24 01:09:00 sybalsky
* past changes
*
* Revision 1.2 1999/01/03 02:06:54 sybalsky
* Add ID comments / static to files for CVS use
*
* Revision 1.1.1.1 1998/12/17 05:03:20 sybalsky
* Import of Medley 3.5 emulator
*
* Revision 4.1 1993/09/15 20:50:44 davy
* GCC fixes from Guy Harris.
*
* Revision 4.1 1993/09/15 20:50:44 davy
* GCC fixes from Guy Harris.
*
* Revision 4.0 1993/03/01 19:59:00 davy
* NFSWATCH Version 4.0.
*
* Revision 1.5 1993/02/19 19:54:36 davy
* Another change in hopes of making things work on SVR4.
*
* Revision 1.4 1993/01/26 13:19:05 davy
* Fixed a goof in passing buffer size.
*
* Revision 1.3 1993/01/26 13:18:39 davy
* Added ifdef's to make it work on DLPI 1.3.
*
* Revision 1.2 1993/01/15 19:33:39 davy
* Miscellaneous cleanups.
*
* Revision 1.1 1993/01/15 15:42:32 davy
* Initial revision
*
*/
#include <sys/param.h>
#include <sys/stropts.h>
#include <sys/stream.h>
#include <sys/dlpi.h>
#ifdef OS5
#include <sys/bufmod.h>
#include <unistd.h>
#include <stdlib.h>
#include <stropts.h>
#include <malloc.h>
#endif
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include "nfswatch.h"
static void dlbindreq();
static void dlinforeq();
static void dlattachreq();
static void dlpromisconreq();
static void sigalrm();
static int dlokack();
static int dlinfoack();
static int dlbindack();
static int expecting();
static int strgetmsg();
static char *savestr();
static char *pname;
extern unsigned char ether_host[6];
int truncation = 1500;
/*
* setup_dlpi_dev - set up the data link provider interface.
*/
int setup_dlpi_dev(char *device)
{
char *p;
u_int chunksz;
char cbuf[BUFSIZ];
struct ifconf ifc;
struct ifreq *ifrp;
struct strioctl si;
char devname[BUFSIZ];
int n, s, fd, devppa;
struct timeval timeout;
long buf[DLPI_MAXDLBUF];
/*
* If the interface device was not specified,
* get the default one.
*/
if ((device == NULL) || *device == NULL) {
/*
* Grab a socket.
*/
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return (-1);
}
ifc.ifc_buf = cbuf;
ifc.ifc_len = sizeof(cbuf);
/*
* See what devices we've got.
*/
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
perror("ioctl: SIOCGIFCONF");
return (-1);
}
/*
* Take the first device we encounter.
*/
ifrp = ifc.ifc_req;
for (n = ifc.ifc_len / sizeof(struct ifreq); n > 0; n--, ifrp++) {
/*
* Skip the loopback interface.
*/
if (strcmp(ifrp->ifr_name, "lo0") == 0) continue;
device = savestr(ifrp->ifr_name);
break;
}
(void)close(s);
}
/*
* Split the device name into type and unit number.
*/
if ((p = strpbrk(device, "0123456789")) == NULL) return (-1);
strcpy(devname, DLPI_DEVDIR);
strncat(devname, device, p - device);
devppa = atoi(p);
/*
* Open the device.
*/
if ((fd = open(devname, O_RDWR)) < 0) {
if (errno == ENOENT || errno == ENXIO) return (-1);
/*perror(devname);*/
return (-1);
}
/*
* Attach to the device. If this fails, the device
* does not exist.
*/
dlattachreq(fd, devppa);
if (dlokack(fd, buf) < 0) {
close(fd);
return (-1);
}
/*
* Bind to the specific unit.
*/
dlbindreq(fd, 0x0600, 0, DL_CLDLS, 0, 0);
if (dlbindack(fd, buf) < 0) {
fprintf(stderr, "%s: dlbindack failed.\n", pname);
return (-1);
}
#ifdef OS5
/*
* We really want all types of packets. However, the SVR4 DLPI does
* not let you have the packet frame header, so we won't be able to
* distinguish protocol types. But SunOS5 gives you the DLIOCRAW
* ioctl to get the frame headers, so we can do this on SunOS5.
*/
dlpromisconreq(fd, DL_PROMISC_SAP);
if (dlokack(fd, buf) < 0) {
fprintf(stderr, "%s: DL_PROMISC_SAP failed.\n", pname);
return (-1);
}
dlpromisconreq(fd, DL_PROMISC_MULTI);
if (dlokack(fd, buf) < 0) {
fprintf(stderr, "%s: DL_PROMISC_MULTI failed.\n", pname);
return (-1);
}
/*
* We want raw packets with the packet frame header. But we can
* only get this in SunOS5 with the DLIOCRAW ioctl; it's not in
* standard SVR4.
*/
si.ic_cmd = DLIOCRAW;
si.ic_timout = -1;
si.ic_len = 0;
si.ic_dp = 0;
if (ioctl(fd, I_STR, &si) < 0) {
perror("ioctl: I_STR DLIOCRAW");
return (-1);
}
#endif /* OS5 */
/*
* Arrange to get discrete messages.
*/
if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
perror("ioctl: I_SRDOPT RMSGD");
return (-1);
}
#ifdef OS5
/*
* Push and configure the streams buffering module. This is once
* again SunOS-specific.
*/
#ifdef NEVER
if (ioctl(fd, I_PUSH, DLPI_BUFMOD) < 0) {
perror("ioctl: I_PUSH BUFMOD");
return (-1);
}
/*
* Set the read timeout.
*/
timeout.tv_sec = 1;
timeout.tv_usec = 0;
si.ic_cmd = SBIOCSTIME;
si.ic_timout = INFTIM;
si.ic_len = sizeof(timeout);
si.ic_dp = (char *)&timeout;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
perror("ioctl: I_STR SBIOCSTIME");
return (-1);
}
/*
* Set the chunk size.
*/
chunksz = DLPI_CHUNKSIZE;
si.ic_cmd = SBIOCSCHUNK;
si.ic_len = sizeof(chunksz);
si.ic_dp = (char *)&chunksz;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
perror("ioctl: I_STR SBIOCSCHUNK");
return (-1);
}
/*
* Set snapshot mode.
*/
si.ic_cmd = SBIOCSSNAP;
si.ic_len = sizeof(truncation);
si.ic_dp = (char *)&truncation;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
perror("ioctl: I_STR SBIOCSSNAP");
return (-1);
}
#endif /* NEVER */
#endif /* OS5 */
return (fd);
}
/*
* flush_dlpi - flush data from the dlpi.
*/
void flush_dlpi(int fd)
{
if (ioctl(fd, I_FLUSH, (char *)FLUSHR) < 0) {
perror("ioctl: I_FLUSH");
return;
}
}
/*
* dlpi_devtype - determine the type of device we're looking at.
*/
int dlpi_devtype(int fd)
{
long buf[DLPI_MAXDLBUF];
union DL_primitives *dlp;
dlp = (union DL_primitives *)buf;
dlinforeq(fd);
if (dlinfoack(fd, buf) < 0) return (DLT_EN10MB);
bcopy((char *)dlp + dlp->info_ack.dl_addr_offset, ether_host, 6);
switch (dlp->info_ack.dl_mac_type) {
case DL_CSMACD:
case DL_ETHER: return (DLT_EN10MB);
#ifdef DL_FDDI
case DL_FDDI: return (DLT_FDDI);
#endif
default:
fprintf(stderr, "%s: DLPI MACtype %ld unknown, ", pname, (long)dlp->info_ack.dl_mac_type);
fprintf(stderr, "assuming ethernet.\n");
return (DLT_EN10MB);
}
}
/*
* dlinforeq - request information about the data link provider.
*/
static void dlinforeq(int fd)
{
dl_info_req_t info_req;
struct strbuf ctl;
int flags;
info_req.dl_primitive = DL_INFO_REQ;
ctl.maxlen = 0;
ctl.len = sizeof(info_req);
ctl.buf = (char *)&info_req;
flags = RS_HIPRI;
if (putmsg(fd, &ctl, (struct strbuf *)NULL, flags) < 0) {
perror("putmsg");
return;
}
}
/*
* dlattachreq - send a request to attach.
*/
static void dlattachreq(int fd, u_long ppa)
{
dl_attach_req_t attach_req;
struct strbuf ctl;
int flags;
attach_req.dl_primitive = DL_ATTACH_REQ;
attach_req.dl_ppa = ppa;
ctl.maxlen = 0;
ctl.len = sizeof(attach_req);
ctl.buf = (char *)&attach_req;
flags = 0;
if (putmsg(fd, &ctl, (struct strbuf *)NULL, flags) < 0) {
perror("putmsg");
return;
}
}
#ifdef DL_PROMISCON_REQ
/*
* dlpromisconreq - send a request to turn promiscuous mode on.
*/
static void dlpromisconreq(int fd, u_long level)
{
dl_promiscon_req_t promiscon_req;
struct strbuf ctl;
int flags;
promiscon_req.dl_primitive = DL_PROMISCON_REQ;
promiscon_req.dl_level = level;
ctl.maxlen = 0;
ctl.len = sizeof(promiscon_req);
ctl.buf = (char *)&promiscon_req;
flags = 0;
if (putmsg(fd, &ctl, (struct strbuf *)NULL, flags) < 0) {
perror("putmsg");
return;
}
}
#endif /* DL_PROMISCON_REQ */
/*
* dlbindreq - send a request to bind.
*/
static void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest)
{
dl_bind_req_t bind_req;
struct strbuf ctl;
int flags;
bind_req.dl_primitive = DL_BIND_REQ;
bind_req.dl_sap = sap;
bind_req.dl_max_conind = max_conind;
bind_req.dl_service_mode = service_mode;
bind_req.dl_conn_mgmt = conn_mgmt;
#ifdef DL_PROMISC_PHYS
/*
* DLPI 2.0 only?
*/
bind_req.dl_xidtest_flg = xidtest;
#endif
ctl.maxlen = 0;
ctl.len = sizeof(bind_req);
ctl.buf = (char *)&bind_req;
flags = 0;
if (putmsg(fd, &ctl, (struct strbuf *)NULL, flags) < 0) {
perror("putmsg");
return;
}
}
/*
* dlokack - general acknowledgement reception.
*/
static int dlokack(int fd, char *bufp)
{
union DL_primitives *dlp;
struct strbuf ctl;
int flags;
ctl.maxlen = DLPI_MAXDLBUF;
ctl.len = 0;
ctl.buf = bufp;
if (strgetmsg(fd, &ctl, (struct strbuf *)NULL, &flags, "dlokack") < 0) return (-1);
dlp = (union DL_primitives *)ctl.buf;
if (expecting(DL_OK_ACK, dlp) < 0) return (-1);
if (ctl.len < sizeof(dl_ok_ack_t)) return (-1);
if (flags != RS_HIPRI) return (-1);
if (ctl.len < sizeof(dl_ok_ack_t)) return (-1);
return (0);
}
/*
* dlinfoack - receive an ack to a dlinforeq.
*/
static int dlinfoack(int fd, char *bufp)
{
union DL_primitives *dlp;
struct strbuf ctl;
int flags;
ctl.maxlen = DLPI_MAXDLBUF;
ctl.len = 0;
ctl.buf = bufp;
if (strgetmsg(fd, &ctl, (struct strbuf *)NULL, &flags, "dlinfoack") < 0) return (-1);
dlp = (union DL_primitives *)ctl.buf;
if (expecting(DL_INFO_ACK, dlp) < 0) return (-1);
if (ctl.len < sizeof(dl_info_ack_t)) return (-1);
if (flags != RS_HIPRI) return (-1);
if (ctl.len < sizeof(dl_info_ack_t)) return (-1);
return (0);
}
/*
* dlbindack - receive an ack to a dlbindreq.
*/
static int dlbindack(int fd, char *bufp)
{
union DL_primitives *dlp;
struct strbuf ctl;
int flags;
ctl.maxlen = DLPI_MAXDLBUF;
ctl.len = 0;
ctl.buf = bufp;
if (strgetmsg(fd, &ctl, (struct strbuf *)NULL, &flags, "dlbindack") < 0) return (-1);
dlp = (union DL_primitives *)ctl.buf;
if (expecting(DL_BIND_ACK, dlp) < 0) return (-1);
if (flags != RS_HIPRI) return (-1);
if (ctl.len < sizeof(dl_bind_ack_t)) return (-1);
return (0);
}
/*
* expecting - see if we got what we wanted.
*/
static int expecting(int prim, union DL_primitives *dlp)
{
if (dlp->dl_primitive != (u_long)prim) return (-1);
return (0);
}
/*
* strgetmsg - get a message from a stream, with timeout.
*/
static int strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller)
{
int rc;
void sigalrm();
/*
* Start timer.
*/
(void)sigset(SIGALRM, sigalrm);
if (alarm(DLPI_MAXWAIT) < 0) {
perror("alarm");
return (-1);
}
/*
* Set flags argument and issue getmsg().
*/
*flagsp = 0;
if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
perror("getmsg");
return (-1);
}
/*
* Stop timer.
*/
if (alarm(0) < 0) {
perror("alarm");
return (-1);
}
/*
* Check for MOREDATA and/or MORECTL.
*/
if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) return (-1);
if (rc & MORECTL) return (-1);
if (rc & MOREDATA) return (-1);
/*
* Check for at least sizeof (long) control data portion.
*/
if (ctlp->len < sizeof(long)) return (-1);
return (0);
}
/*
* sigalrm - handle alarms.
*/
static void sigalrm() { (void)fprintf(stderr, "dlpi: timeout\n"); }
/*
* savestr - save string in dynamic memory.
*/
char *savestr(char *s)
{
char *t;
if ((t = malloc(strlen(s) + 1)) == NULL) {
(void)fprintf(stderr, "%s: out of memory.\n", pname);
(void)exit(1);
}
(void)strcpy(t, s);
return (t);
}
int dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen)
{
long buf[DLPI_MAXDLBUF];
union DL_primitives *dlp;
struct strbuf data, ctl;
dlp = (union DL_primitives *)buf;
dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
dlp->unitdata_req.dl_dest_addr_length = addrlen + 2;
dlp->unitdata_req.dl_dest_addr_offset = sizeof(dl_unitdata_req_t);
dlp->unitdata_req.dl_priority.dl_min = minpri;
dlp->unitdata_req.dl_priority.dl_max = maxpri;
(void)memcpy(OFFADDR(dlp, sizeof(dl_unitdata_req_t)), addrp, addrlen);
(void)memcpy(OFFADDR(dlp, sizeof(dl_unitdata_req_t) + addrlen), (char *)addrp + 12, 2);
ctl.maxlen = 0;
ctl.len = sizeof(dl_unitdata_req_t) + addrlen + 2;
ctl.buf = (char *)buf;
data.maxlen = 0;
data.len = datalen;
data.buf = (char *)datap;
#ifdef NEVER
if (putmsg(fd, &ctl, &data, 0) < 0)
#else
if (putmsg(fd, NULL, &data, 0) < 0)
#endif /* NEVER tst on 9/30/96 jds to see if raw out works */
return -1;
else
return 0;
}
#endif /* USE_DLPI */