📄 eth-dlpi.c
字号:
/* * eth-dlpi.c * * Based on Neal Nuckolls' 1992 "How to Use DLPI" paper. * * Copyright (c) 2001 Dug Song <dugsong@monkey.org> * * $Id: eth-dlpi.c,v 1.19 2005/02/10 16:48:36 dugsong Exp $ */#include "config.h"#include <sys/types.h>#ifdef HAVE_SYS_BUFMOD_H#include <sys/bufmod.h>#endif#ifdef HAVE_SYS_DLPI_H#include <sys/dlpi.h>#elif defined(HAVE_SYS_DLPIHDR_H)#include <sys/dlpihdr.h>#endif#ifdef HAVE_SYS_DLPI_EXT_H#include <sys/dlpi_ext.h>#endif#include <sys/stream.h>#include <assert.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stropts.h>#include <unistd.h>#include "dnet.h"#ifndef INFTIM#define INFTIM -1#endifstruct eth_handle { int fd; int sap_len;};static intdlpi_msg(int fd, union DL_primitives *dlp, int rlen, int flags, int ack, int alen, int size){ struct strbuf ctl; ctl.maxlen = 0; ctl.len = rlen; ctl.buf = (caddr_t)dlp; if (putmsg(fd, &ctl, NULL, flags) < 0) return (-1); ctl.maxlen = size; ctl.len = 0; flags = 0; if (getmsg(fd, &ctl, NULL, &flags) < 0) return (-1); if (dlp->dl_primitive != ack || ctl.len < alen) return (-1); return (0);}#if defined(DLIOCRAW) || defined(HAVE_SYS_DLPIHDR_H)static intstrioctl(int fd, int cmd, int len, char *dp){ struct strioctl str; str.ic_cmd = cmd; str.ic_timout = INFTIM; str.ic_len = len; str.ic_dp = dp; if (ioctl(fd, I_STR, &str) < 0) return (-1); return (str.ic_len);}#endif#ifdef HAVE_SYS_DLPIHDR_H/* XXX - OSF1 is nuts */#define ND_GET ('N' << 8 + 0)static inteth_match_ppa(eth_t *e, const char *device){ char *p, dev[16], buf[256]; int len, ppa; strlcpy(buf, "dl_ifnames", sizeof(buf)); if ((len = strioctl(e->fd, ND_GET, sizeof(buf), buf)) < 0) return (-1); for (p = buf; p < buf + len; p += strlen(p) + 1) { ppa = -1; if (sscanf(p, "%s (PPA %d)\n", dev, &ppa) != 2) break; if (strcmp(dev, device) == 0) break; } return (ppa);}#endifeth_t *eth_open(const char *device){ union DL_primitives *dlp; uint32_t buf[8192]; char *p, dev[16]; eth_t *e; int ppa; if ((e = calloc(1, sizeof(*e))) == NULL) return (NULL);#ifdef HAVE_SYS_DLPIHDR_H if ((e->fd = open("/dev/streams/dlb", O_RDWR)) < 0) return (eth_close(e)); if ((ppa = eth_match_ppa(e, device)) < 0) { errno = ESRCH; return (eth_close(e)); }#else e->fd = -1; snprintf(dev, sizeof(dev), "/dev/%s", device); if ((p = strpbrk(dev, "0123456789")) == NULL) { errno = EINVAL; return (eth_close(e)); } ppa = atoi(p); *p = '\0'; if ((e->fd = open(dev, O_RDWR)) < 0) { snprintf(dev, sizeof(dev), "/dev/%s", device); if ((e->fd = open(dev, O_RDWR)) < 0) return (eth_close(e)); }#endif dlp = (union DL_primitives *)buf; dlp->info_req.dl_primitive = DL_INFO_REQ; if (dlpi_msg(e->fd, dlp, DL_INFO_REQ_SIZE, RS_HIPRI, DL_INFO_ACK, DL_INFO_ACK_SIZE, sizeof(buf)) < 0) return (eth_close(e)); e->sap_len = dlp->info_ack.dl_sap_length; if (dlp->info_ack.dl_provider_style == DL_STYLE2) { dlp->attach_req.dl_primitive = DL_ATTACH_REQ; dlp->attach_req.dl_ppa = ppa; if (dlpi_msg(e->fd, dlp, DL_ATTACH_REQ_SIZE, 0, DL_OK_ACK, DL_OK_ACK_SIZE, sizeof(buf)) < 0) return (eth_close(e)); } memset(&dlp->bind_req, 0, DL_BIND_REQ_SIZE); dlp->bind_req.dl_primitive = DL_BIND_REQ;#ifdef DL_HP_RAWDLS dlp->bind_req.dl_sap = 24; /* from HP-UX DLPI programmers guide */ dlp->bind_req.dl_service_mode = DL_HP_RAWDLS;#else dlp->bind_req.dl_sap = DL_ETHER; dlp->bind_req.dl_service_mode = DL_CLDLS;#endif if (dlpi_msg(e->fd, dlp, DL_BIND_REQ_SIZE, 0, DL_BIND_ACK, DL_BIND_ACK_SIZE, sizeof(buf)) < 0) return (eth_close(e));#ifdef DLIOCRAW if (strioctl(e->fd, DLIOCRAW, 0, NULL) < 0) return (eth_close(e));#endif return (e);}ssize_teth_send(eth_t *e, const void *buf, size_t len){#if defined(DLIOCRAW) return (write(e->fd, buf, len));#else union DL_primitives *dlp; struct strbuf ctl, data; struct eth_hdr *eth; uint32_t ctlbuf[8192]; u_char sap[4] = { 0, 0, 0, 0 }; int dlen; dlp = (union DL_primitives *)ctlbuf;#ifdef DL_HP_RAWDATA_REQ dlp->dl_primitive = DL_HP_RAWDATA_REQ; dlen = DL_HP_RAWDATA_REQ_SIZE;#else dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; dlp->unitdata_req.dl_dest_addr_length = ETH_ADDR_LEN; dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE; dlp->unitdata_req.dl_priority.dl_min = dlp->unitdata_req.dl_priority.dl_max = 0; dlen = DL_UNITDATA_REQ_SIZE;#endif eth = (struct eth_hdr *)buf; *(uint16_t *)sap = ntohs(eth->eth_type); /* XXX - DLSAP setup logic from ISC DHCP */ ctl.maxlen = 0; ctl.len = dlen + ETH_ADDR_LEN + abs(e->sap_len); ctl.buf = (char *)ctlbuf; if (e->sap_len >= 0) { memcpy(ctlbuf + dlen, sap, e->sap_len); memcpy(ctlbuf + dlen + e->sap_len, eth->eth_dst.data, ETH_ADDR_LEN); } else { memcpy(ctlbuf + dlen, eth->eth_dst.data, ETH_ADDR_LEN); memcpy(ctlbuf + dlen + ETH_ADDR_LEN, sap, abs(e->sap_len)); } data.maxlen = 0; data.len = len; data.buf = (char *)buf; if (putmsg(e->fd, &ctl, &data, 0) < 0) return (-1); return (len);#endif}eth_t *eth_close(eth_t *e){ if (e != NULL) { if (e->fd >= 0) close(e->fd); free(e); } return (NULL);}inteth_get(eth_t *e, eth_addr_t *ea){ union DL_primitives *dlp; u_char buf[2048]; dlp = (union DL_primitives *)buf; dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR; if (dlpi_msg(e->fd, dlp, DL_PHYS_ADDR_REQ_SIZE, 0, DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE, sizeof(buf)) < 0) return (-1); memcpy(ea, buf + dlp->physaddr_ack.dl_addr_offset, sizeof(*ea)); return (0);}inteth_set(eth_t *e, const eth_addr_t *ea){ union DL_primitives *dlp; u_char buf[2048]; dlp = (union DL_primitives *)buf; dlp->set_physaddr_req.dl_primitive = DL_SET_PHYS_ADDR_REQ; dlp->set_physaddr_req.dl_addr_length = ETH_ADDR_LEN; dlp->set_physaddr_req.dl_addr_offset = DL_SET_PHYS_ADDR_REQ_SIZE; memcpy(buf + DL_SET_PHYS_ADDR_REQ_SIZE, ea, sizeof(*ea)); return (dlpi_msg(e->fd, dlp, DL_SET_PHYS_ADDR_REQ_SIZE + ETH_ADDR_LEN, 0, DL_OK_ACK, DL_OK_ACK_SIZE, sizeof(buf)));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -