📄 pktdrive.c
字号:
return 0;}/* * Routines specific to the fake PPP layer used by the Niwot packet driver. * Does nothing but add two bytes of type field at the front of the packet. * * The magic type code is byte[0] = 0x00, byte[1] = 0x21. * This was determined empirically. * * We don't know (or really care) who came up with this silliness, it's not * a particularly bad idea, it's just not PPP and shouldn't be called that. *//* Receive a fake PPP packet; update the MIB counters and hand it up to IP. */static void fppp_rcv(struct packet *p){ bits16_t pkt_type;#if INSTALL_ATTACHE_MIB p->pkt_n->ifInOctets += p->pkt_datalen;#endif MIB_COUNTER_INC(p->pkt_n->ifInUcastPkts); /* pull out the type field */ if (p->pkt_datalen < 2) { MIB_COUNTER_INC(p->pkt_n->ifInErrors); pkt_free(p); return; } pkt_type = p->pkt_data[0] << 8; pkt_type |= p->pkt_data[1]; p->pkt_data += 2; p->pkt_datalen -= 2; /* hand the packet up to the next layer */ if (pkt_type == 0x0021) { ip_rcv(p); } else { MIB_COUNTER_INC(p->pkt_n->ifInUnknownProtos); pkt_free(p); }}/* * Send an IP packet; put in the type field, update the MIB counters * and hand it off to the packet driver as a fake PPP packet. */static void fppp_ip_send(struct net *net, struct packet *p, inaddr_t dest){ p->pkt_n = net; /* make space for the type field */ p->pkt_data -= 2; if (p->pkt_data < p->pkt_buffer) { /* If this happens then things are bad */ pkt_free(p); return; } p->pkt_datalen += 2; /* Type PPP_IP */ p->pkt_data[0] = 0; p->pkt_data[1] = 0x21;#if INSTALL_ATTACHE_MIB net->ifOutOctets += p->pkt_datalen;#endif MIB_COUNTER_INC(net->ifOutUcastPkts); pktd_send(p);}#if !INSTALL_ATTACHE_PPP || !SNARK_PKTDRV_PPP_OVER_SLIP/* * Slip packet driver routines. *//* * Receive a SLIP packet; update the MIB counters and hand it up to IP. */static void slip_rcv(struct packet *p){#if INSTALL_ATTACHE_MIB p->pkt_n->ifInOctets += p->pkt_datalen;#endif MIB_COUNTER_INC(p->pkt_n->ifInUcastPkts); ip_rcv(p);}/* * Send an IP packet; update MIB counters and hand off to packet driver. */static void slip_ip_send(struct net *net, struct packet *p, inaddr_t dest){ p->pkt_n = net;#if INSTALL_ATTACHE_MIB net->ifOutOctets += p->pkt_datalen;#endif MIB_COUNTER_INC(net->ifOutUcastPkts); pktd_send(p);}#endif /* !INSTALL_ATTACHE_PPP || !SNARK_PKTDRV_PPP_OVER_SLIP *//* * Driver interface structures for the various media types we understand * via packet drivers. *//* The ethernet packet driver interface structure */static struct driver pd_ether_driver = { pktd_init, pktd_send,#if INSTALL_ATTACHE_34_IPV4_API_COMPAT et_ip_send,#else 0,#endif et_arp_send, 0, /* test routine */ pktd_close, "ether", /* short name */ "FTP Software Packet Driver", /* long name */ 14, /* local net header */ 0, /* local net trailer */ 1514, /* MTU */ IF_ETHERNET, ARP_HEADER_HARDWARE_TYPE_is_ETHERNET,#if !INSTALL_ATTACHE_ETHERNET_NO_MEDIA_CTL et_media_ctl, /* Media control routine, if installed */#else 0,#endif#if INSTALL_ATTACHE_IPV6 et_ipv6_send, /* IPv6 send routine, if installed */#else 0,#endif#if INSTALL_ATTACHE_IPV4 et_ipv4_send, /* IPv4 send routine, if installed */#else 0,#endif /* INSTALL_ATTACHE_IPV4 */};/* * The serial line (SLIP) packet driver interface structure. */#if !INSTALL_ATTACHE_PPP || !SNARK_PKTDRV_PPP_OVER_SLIPstatic struct driver pd_serial_driver = { pktd_init, pktd_send, slip_ip_send, 0, /* arp send */ 0, /* test routine */ pktd_close, "slip", /* short name */ "FTP Software Packet Driver", /* long name */ 0, /* local net header */ 0, /* local net trailer */ 1514, /* MTU */ IF_SLIP, 0, /* arp hardware type */ 0, /* media control */ 0, /* IPv6 send */ 0 /* IPv4 send */};#endif /* !INSTALL_ATTACHE_PPP || !SNARK_PKTDRV_PPP_OVER_SLIP *//* * The Point to Point Protocol (PPP) packet driver interface structure. */#if INSTALL_ATTACHE_PPP && SNARK_PKTDRV_PPP_OVER_SLIPstatic struct driver pd_ppp_driver = { pktd_init, pktd_send, ppp_ip_send, 0, /* arp send */ 0, /* test routine */ pktd_close, "ppp", /* short name */ "FTP Software Packet Driver", /* long name */ 4, /* local net header */ 0, /* local net trailer */ 1514, /* MTU */ IF_PPP, 0, /* arp hardware type */ ppp_control, /* media control */ 0, /* IPv6 send */ 0 /* IPv4 send */};#endif /* INSTALL_ATTACHE_PPP && SNARK_PKTDRV_PPP_OVER_SLIP *//* * The "fake PPP" packet driver interface structure. */static struct driver pd_fppp_driver = { pktd_init, pktd_send, fppp_ip_send, 0, /* arp send */ 0, /* test routine */ pktd_close, "fppp", /* short name */ "FTP Software Packet Driver", /* long name */ 0, /* local net header */ 0, /* local net trailer */ 1514, /* MTU */ IF_PPP, 0, /* arp hardware type */ 0, /* media control */ 0, /* IPv6 send */ 0 /* IPv4 send */};/* * The packet receive routines. We have several instances of essentially the * same routine because the only information we have about which packet driver * is calling us is given by which routine is called. Closures would be nice. * The macro that produces this routine is defined in system.h. I'll have to * come up with something else for those C compilers which can't generate such * a routine from C source and needs assembly language instead. */PD_UPCALL(pktd_receive60, pd_nets[0x00], pktd_receive)PD_UPCALL(pktd_receive61, pd_nets[0x01], pktd_receive)PD_UPCALL(pktd_receive62, pd_nets[0x02], pktd_receive)PD_UPCALL(pktd_receive63, pd_nets[0x03], pktd_receive)PD_UPCALL(pktd_receive64, pd_nets[0x04], pktd_receive)PD_UPCALL(pktd_receive65, pd_nets[0x05], pktd_receive)PD_UPCALL(pktd_receive66, pd_nets[0x06], pktd_receive)PD_UPCALL(pktd_receive67, pd_nets[0x07], pktd_receive)PD_UPCALL(pktd_receive68, pd_nets[0x08], pktd_receive)PD_UPCALL(pktd_receive69, pd_nets[0x09], pktd_receive)PD_UPCALL(pktd_receive6a, pd_nets[0x0a], pktd_receive)PD_UPCALL(pktd_receive6b, pd_nets[0x0b], pktd_receive)PD_UPCALL(pktd_receive6c, pd_nets[0x0c], pktd_receive)PD_UPCALL(pktd_receive6d, pd_nets[0x0d], pktd_receive)PD_UPCALL(pktd_receive6e, pd_nets[0x0e], pktd_receive)PD_UPCALL(pktd_receive6f, pd_nets[0x0f], pktd_receive)PD_UPCALL(pktd_receive70, pd_nets[0x10], pktd_receive)PD_UPCALL(pktd_receive71, pd_nets[0x11], pktd_receive)PD_UPCALL(pktd_receive72, pd_nets[0x12], pktd_receive)PD_UPCALL(pktd_receive73, pd_nets[0x13], pktd_receive)PD_UPCALL(pktd_receive74, pd_nets[0x14], pktd_receive)PD_UPCALL(pktd_receive75, pd_nets[0x15], pktd_receive)PD_UPCALL(pktd_receive76, pd_nets[0x16], pktd_receive)PD_UPCALL(pktd_receive77, pd_nets[0x17], pktd_receive)PD_UPCALL(pktd_receive78, pd_nets[0x18], pktd_receive)PD_UPCALL(pktd_receive79, pd_nets[0x19], pktd_receive)PD_UPCALL(pktd_receive7a, pd_nets[0x1a], pktd_receive)PD_UPCALL(pktd_receive7b, pd_nets[0x1b], pktd_receive)PD_UPCALL(pktd_receive7c, pd_nets[0x1c], pktd_receive)PD_UPCALL(pktd_receive7d, pd_nets[0x1d], pktd_receive)PD_UPCALL(pktd_receive7e, pd_nets[0x1e], pktd_receive)PD_UPCALL(pktd_receive7f, pd_nets[0x1f], pktd_receive)/* * Indexed by packet driver interrupt (0 index = PKTDRVR_MIN_INT). */static PD_UPCALL_RTN_T *pd_upcalls[PKTDRVR_MAX_INT - PKTDRVR_MIN_INT + 1] = { pktd_receive60, pktd_receive61, pktd_receive62, pktd_receive63, pktd_receive64, pktd_receive65, pktd_receive66, pktd_receive67, pktd_receive68, pktd_receive69, pktd_receive6a, pktd_receive6b, pktd_receive6c, pktd_receive6d, pktd_receive6e, pktd_receive6f, pktd_receive70, pktd_receive71, pktd_receive72, pktd_receive73, pktd_receive74, pktd_receive75, pktd_receive76, pktd_receive77, pktd_receive78, pktd_receive79, pktd_receive7a, pktd_receive7b, pktd_receive7c, pktd_receive7d, pktd_receive7e, pktd_receive7f,};/* * Allocates, initializes, and returns an Attache network interface for a * packet driver. The network is configured with IP addresses and is marked * as down (the packet driver init routine marks it up). */static struct net *pktd_create_net(int pd_int){ struct pktdif *pif;#if INSTALL_ATTACHE_PPP && SNARK_PKTDRV_PPP_OVER_SLIP struct pppctl *pc;#endif /* * Allocate a block of memory for our combined interface information. */ if ((pif = (struct pktdif *) GLUE_ALLOC(sizeof(*pif))) == 0) return 0; MEMSET(pif, 0, sizeof(*pif)); /* * Set up all the internal pointers between the various chunks of data. */ pif->net.s_name = pif->name; pif->net.specific = pif; pif->net.instance = pd_int; pif->net.flags = NF_DRIVER_DOWN; pif->net.ip_bcast = 0xFFFFFFFFL; pif->pdn.pd_int = pd_int; pif->pkt_q_tail = &pif->pkt_q_head; task_ini(&pif->task); pif->task.name = pif->name; pif->task.func = pktd_handler; pif->task.cookie = pif; pif->saved_rcv_mode = -1; /* * Get the driver info. */ switch (pd_driver_info(0, &pif->pdn)) { case PDE_BAD_HANDLE: /* * Older packet drivers might do this. Just assume it's an * ethernet and get the rest of the information later. */ pif->pdn.drvr_info.version = 0; pif->pdn.drvr_info.class = IC_ETHERNET; pif->pdn.drvr_info.pdtype = IT_ANY; pif->pdn.drvr_info.number = 0; pif->pdn.drvr_info.name = "unknown packet driver"; pif->pdn.drvr_info.basic_flag = PDFC_BASIC; break; case PDE_NO_ERROR: /* * We got the information, so continue processing. */ break; default: /* * Any other error is bad, can't use this interface. */ GLUE_FREE(pif); return 0; } /* * Pick the right Attache driver for this packet driver, set it up. */ switch (pif->pdn.drvr_info.class) { case IC_ETHERNET: pif->net.driver = &pd_ether_driver; pif->net.flags |= NF_ARP; pif->net.speed = 10000000L; pif->receiver = et_rcv; break; case IC_SERIAL_LINE:#if INSTALL_ATTACHE_PPP && SNARK_PKTDRV_PPP_OVER_SLIP /* * This is a hack for testing PPP. I use a SLIP packet driver for * the driver and framing. This loses some of the capabilities of * PPP, no async control map, but it lets me test the main parts * of the PPP protocol. */ pif->net.driver = &pd_ppp_driver; pif->net.speed = 9600; /* should get this from the packet driver */ pif->receiver = ppp_rcv; pif->pdn.drvr_info.pdtype = -1; if ((pc = GLUE_ALLOC(sizeof(struct pppctl))) == 0) { printf("Couldn't allocate storage for PPP control block\n"); GLUE_FREE(pif); return 0; } MEMSET(pc, 0, sizeof(struct pppctl)); pc->max_terminate = 5; pc->max_configure = 5;/* pc->ctl_flags = PPPC_FCS; */ pc->ctl_flags = 0; pc->restart_timeout = 5000L; /* 5 seconds */ pif->net.media_cookie = pc;#else /* INSTALL_ATTACHE_PPP && SNARK_PKTDRV_PPP_OVER_SLIP */ pif->net.driver = &pd_serial_driver; pif->net.speed = 9600L; /* should get this from the packet driver */ pif->receiver = slip_rcv; pif->pdn.drvr_info.pdtype = -1;#endif /* INSTALL_ATTACHE_PPP && SNARK_PKTDRV_PPP_OVER_SLIP */ break; case IC_FPPP: pif->net.driver = &pd_fppp_driver; pif->net.speed = 56000L; /* does the packet driver know? */ pif->receiver = fppp_rcv; pif->pdn.drvr_info.pdtype = -1; break; default: printf("Don't know class %d for packet driver %02x\n", pif->pdn.drvr_info.class, pd_int); GLUE_FREE(pif); return 0; } /* * Finally, set up the common stuff. */ pif->net.mtu = pif->net.driver->maxlen - pif->net.driver->lnh + pif->net.driver->lnt; sprintf(pif->name, "%.*s%02x", sizeof(pif->name) - 3, pif->net.driver->prefix, pif->net.instance); pif->pdn.device_receive_rtn = pd_upcalls[pd_int - PKTDRVR_MIN_INT]; pd_nets[pd_int - PKTDRVR_MIN_INT] = &pif->pdn; /* pif->net.driver->name = far_strdup(pif->pdn.drvr_info.name); */ /* * Done, return the new interface. */ return &pif->net;}/* * Find all the packet drivers, build net structures for them, and call the * configuration routine for each of them. If the configuration routine * returns success, attach the interface. */void pktd_driver_find(boolean_t (*config)(struct net *)){ struct net *net; int pd_int; for (pd_int = PKTDRVR_MIN_INT; pd_int <= PKTDRVR_MAX_INT; pd_int++) { if (pd_check_int(pd_int) && (net = pktd_create_net(pd_int)) != 0) { if ((*config)(net)) { net->flags |= NF_DOWN; if_attach(net); if_up(net); } else { GLUE_FREE(net->specific); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -