pktdrvr.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:12k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Driver for FTP Software's packet driver interface. (PC specific code)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <dos.h>
  6. #include "global.h"
  7. #include "proc.h"
  8. #include "mbuf.h"
  9. #include "netuser.h"
  10. #include "enet.h"
  11. #include "arcnet.h"
  12. #include "ax25.h"
  13. #include "slip.h"
  14. #include "kiss.h"
  15. #include "iface.h"
  16. #include "arp.h"
  17. #include "trace.h"
  18. #include "pktdrvr.h"
  19. #include "config.h"
  20. #include "devparam.h"
  21. static long access_type(int intno,int if_class,int if_type,
  22. int if_number, uint8 *type,unsigned typelen,
  23. INTERRUPT (*receiver)(void) );
  24. static int driver_info(int intno,int handle,int *version,
  25. int *class,int *type,int *number,int *basic);
  26. static int release_type(int intno,int handle);
  27. static int get_address(int intno,int handle,uint8 *buf,int len);
  28. static int set_rcv_mode(int intno,int handle,int mode);
  29. static int pk_raw(struct iface *iface,struct mbuf **bpp);
  30. static int pk_stop(struct iface *iface);
  31. static int send_pkt(int intno,uint8 *buffer,unsigned length);
  32. static INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  33. static struct pktdrvr Pktdrvr[PK_MAX];
  34. static int Derr;
  35. char Pkt_sig[] = "PKT DRVR"; /* Packet driver signature */
  36. /*
  37.  * Send routine for packet driver
  38.  */
  39. int
  40. pk_send(
  41. struct mbuf **bpp, /* Buffer to send */
  42. struct iface *iface, /* Pointer to interface control block */
  43. int32 gateway, /* Ignored  */
  44. uint8 tos
  45. ){
  46. if(iface == NULL){
  47. free_p(bpp);
  48. return -1;
  49. }
  50. return (*iface->raw)(iface,bpp);
  51. }
  52. /* Send raw packet (caller provides header) */
  53. static int
  54. pk_raw(
  55. struct iface *iface, /* Pointer to interface control block */
  56. struct mbuf **bpp /* Data field */
  57. ){
  58. register struct pktdrvr *pp;
  59. uint16 size;
  60. struct mbuf *bp1;
  61. iface->rawsndcnt++;
  62. iface->lastsent = secclock();
  63. dump(iface,IF_TRACE_OUT,*bpp);
  64. pp = &Pktdrvr[iface->dev];
  65. size = len_p(*bpp);
  66. /* Perform class-specific processing, if any */
  67. switch(pp->class){
  68. case CL_ETHERNET:
  69. if(size < RUNT){
  70. /* Pad the packet out to the minimum */
  71. #ifdef SECURE
  72. /* This option copies the packet to a new mbuf,
  73.  * padded out with zeros. Otherwise we just lie
  74.  * to the packet driver about the length, and it
  75.  * will spit out bytes beyond the end of the mbuf
  76.  * that might be compromising. The cost is another
  77.  * alloc, free and copy.
  78.  */
  79. bp1 = ambufw(RUNT);
  80. bp1->cnt = RUNT;
  81. memset(bp1->data+size,0,RUNT-size);
  82. pullup(bpp,bp1->data,size);
  83. free_p(bpp); /* Shouldn't be necessary */
  84. *bpp = bp1;
  85. #endif
  86. size = RUNT;
  87. }
  88. break;
  89. case CL_KISS:
  90. /* This *really* shouldn't be done here, but it was the
  91.  * easiest way. Put the type field for KISS TNC on front.
  92.  */
  93. pushdown(bpp,NULL,1);
  94. (*bpp)->data[0] = PARAM_DATA;
  95. size++;
  96. break;
  97. }
  98. if((*bpp)->next != NULL){
  99. /* Copy to contiguous buffer, since driver can't handle mbufs */
  100. bp1 = copy_p(*bpp,size);
  101. free_p(bpp);
  102. *bpp = bp1;
  103. if(*bpp == NULL)
  104. return -1;
  105. }
  106. send_pkt(pp->intno,(*bpp)->data,size);
  107. free_p(bpp);
  108. return 0;
  109. }
  110. /* Packet driver receive upcall routine. Called by the packet driver TSR
  111.  * twice for each incoming packet: first with ax == 0 to allocate a buffer,
  112.  * and then with ax == 1 to signal completion of the copy.
  113.  *
  114.  * The packet driver actually calls an assembler hook (pkvec* in pkvec.s)
  115.  * that passes the driver's ax and cx registers to us as args.
  116.  * It then passes our return value back to the packet driver in es:di.
  117.  *
  118.  * Note that pushing es and di to us as args that we can modify only
  119.  * works reliably when the function is of type "interrupt". Otherwise the
  120.  * compiler can cache the args in registers and optimize out the stores back
  121.  * into the stack since C args are normally call-by-value.
  122.  */
  123. uint8 *
  124. pkint(
  125. int dev,
  126. unsigned short cx,
  127. unsigned short ax
  128. ){
  129. register struct pktdrvr *pp;
  130. uint8 *retval = NULL;
  131. if(dev < 0 || dev >= PK_MAX)
  132. return NULL; /* Unknown device */
  133. pp = &Pktdrvr[dev];
  134. if(pp->iface == NULL)
  135. return NULL; /* Unknown device */
  136. switch(ax){
  137. case 0: /* Space allocate call */
  138. if((pp->buffer = alloc_mbuf(cx+sizeof(struct iface *))) != NULL){
  139. pp->buffer->data += sizeof(struct iface *);
  140. pp->buffer->cnt = cx;
  141. retval = pp->buffer->data;
  142. }
  143. break;
  144. case 1: /* Packet complete call */
  145. net_route(pp->iface,&pp->buffer);
  146. break;
  147. default:
  148. break;
  149. }
  150. return retval;
  151. }
  152. /* Shut down the packet interface */
  153. static int
  154. pk_stop(
  155. struct iface *iface
  156. ){
  157. struct pktdrvr *pp;
  158. pp = &Pktdrvr[iface->dev];
  159. /* Call driver's release_type() entry */
  160. if(release_type(pp->intno,pp->handle1) == -1)
  161. printf("%s: release_type error code %un",iface->name,Derr);
  162. if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  163. release_type(pp->intno,pp->handle2);
  164. release_type(pp->intno,pp->handle3);
  165. }
  166. pp->iface = NULL;
  167. return 0;
  168. }
  169. /* Attach a packet driver to the system
  170.  * argv[0]: hardware type, must be "packet"
  171.  * argv[1]: software interrupt vector, e.g., x7e
  172.  * argv[2]: interface label, e.g., "trw0"
  173.  * argv[3]: maximum number of packets allowed on transmit queue, e.g., "5"
  174.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  175.  * argv[5]: IP address (optional)
  176.  */
  177. int
  178. pk_attach(
  179. int argc,
  180. char *argv[],
  181. void *p
  182. ){
  183. register struct iface *if_pk;
  184. int class,type;
  185. unsigned int intno;
  186. static uint8 iptype[] = {IP_TYPE >> 8,IP_TYPE};
  187. static uint8 arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  188. static uint8 revarptype[] = {REVARP_TYPE >> 8, REVARP_TYPE};
  189. long handle;
  190. int i;
  191. #ifdef ARCNET
  192. static uint8 arcip[] = {ARC_IP};
  193. static uint8 arcarp[] = {ARC_ARP};
  194. #endif
  195. long drvvec;
  196. char sig[8]; /* Copy of driver signature "PKT DRVR" */
  197. register struct pktdrvr *pp;
  198. char tmp[25];
  199. char *cp;
  200. for(i=0;i<PK_MAX;i++){
  201. if(Pktdrvr[i].iface == NULL)
  202. break;
  203. }
  204. if(i >= PK_MAX){
  205. printf("Too many packet driversn");
  206. return -1;
  207. }
  208. if(if_lookup(argv[2]) != NULL){
  209. printf("Interface %s already existsn",argv[2]);
  210. return -1;
  211. }
  212. intno = htoi(argv[1]);
  213. /* Verify that there's really a packet driver there, so we don't
  214.  * go off into the ozone (if there's any left)
  215.  */
  216. drvvec = (long)getvect(intno);
  217. movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  218. FP_OFF(sig),FP_SEG(sig),strlen(Pkt_sig));
  219. if(strncmp(sig,Pkt_sig,strlen(Pkt_sig)) != 0){
  220. printf("No packet driver loaded at int 0x%xn",intno);
  221. return -1;
  222. }
  223. if_pk = (struct iface *)callocw(1,sizeof(struct iface));
  224. if_pk->name = strdup(argv[2]);
  225. if(argc > 5)
  226. if_pk->addr = resolve(argv[5]);
  227. else
  228. if_pk->addr = Ip_addr;
  229. pp = &Pktdrvr[i];
  230. if_pk->mtu = atoi(argv[4]);
  231. if_pk->dev = i;
  232. if_pk->raw = pk_raw;
  233. if_pk->stop = pk_stop;
  234. pp->intno = intno;
  235. pp->iface = if_pk;
  236.   /* Version 1.08 of the packet driver spec dropped the handle
  237.    * requirement from the driver_info call.  However, if we are using
  238.    * a version 1.05 packet driver, the following call will fail.
  239.     */
  240.   if(driver_info(intno,-1,NULL,&class,&type,NULL,NULL) < 0){
  241. /* Find out by exhaustive search what class this driver is (ugh) */
  242. for(class=1;class<=NCLASS;class++){
  243. /* Store handle in temp long so we can tell an
  244.  * error return (-1) from a handle of 0xffff
  245.  */
  246. handle = access_type(intno,class,ANYTYPE,0,iptype,2,
  247. Pkvec[if_pk->dev]);
  248. if(handle != -1 || Derr == TYPE_INUSE){
  249. pp->handle1 = handle;
  250. break;
  251. }
  252. }
  253. /* Now that we know, release it and do it all over again with the
  254.  * right type fields
  255.  */
  256. release_type(intno,pp->handle1);
  257. }
  258. switch(class){
  259. case CL_ETHERNET:
  260. pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  261. Pkvec[if_pk->dev]);
  262. pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  263. Pkvec[if_pk->dev]);
  264. pp->handle3 = access_type(intno,class,ANYTYPE,0,revarptype,2,
  265. Pkvec[if_pk->dev]);
  266. setencap(if_pk,"Ethernet");
  267. /**** temp set multicast flag ****/
  268. /* i = set_rcv_mode(intno,pp->handle1,5);
  269. printf("set_rcv_mode returns %d, Derr = %dn",i,Derr); */
  270. /* Get hardware Ethernet address from driver */
  271. if_pk->hwaddr = mallocw(EADDR_LEN);
  272. get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  273. if(if_pk->hwaddr[0] & 1){
  274. printf("Warning! Interface '%s' has a multicast address:",
  275.  if_pk->name);
  276. printf(" (%s)n",
  277.  (*if_pk->iftype->format)(tmp,if_pk->hwaddr));
  278. }
  279. break;
  280. #ifdef ARCNET
  281. case CL_ARCNET:
  282. pp->handle1 = access_type(intno,class,ANYTYPE,0,arcip,1,
  283. Pkvec[if_pk->dev]);
  284. pp->handle2 = access_type(intno,class,ANYTYPE,0,arcarp,1,
  285. Pkvec[if_pk->dev]);
  286. if_pk->output = anet_output;
  287. /* Get hardware ARCnet address from driver */
  288. if_pk->hwaddr = mallocw(AADDR_LEN);
  289. get_address(intno,pp->handle1,if_pk->hwaddr,AADDR_LEN);
  290. break;
  291. #endif
  292. case CL_SERIAL_LINE:
  293. pp->handle1 = access_type(intno,class,ANYTYPE,0,NULL,0,
  294.  Pkvec[if_pk->dev]);
  295. setencap(if_pk,"SLIP");
  296. break;
  297. #ifdef AX25
  298. case CL_KISS: /* Note that the raw routine puts on the command */
  299. case CL_AX25:
  300. pp->handle1 = access_type(intno,class,ANYTYPE,0,NULL,0,
  301.  Pkvec[if_pk->dev]);
  302. setencap(if_pk,"AX25");
  303. if_pk->hwaddr = mallocw(AXALEN);
  304. memcpy(if_pk->hwaddr,Mycall,AXALEN);
  305. break;
  306. #endif
  307. case CL_SLFP:
  308. pp->handle1 = access_type(intno,class,ANYTYPE,0,NULL,0,
  309.  Pkvec[if_pk->dev]);
  310. setencap(if_pk,"SLFP");
  311. get_address(intno,pp->handle1,(uint8 *)&if_pk->addr,4);
  312. break;
  313. default:
  314. printf("Packet driver has unsupported class %un",class);
  315. free(if_pk->name);
  316. free(if_pk);
  317. return -1;
  318. }
  319. pp->class = class;
  320. if_pk->next = Ifaces;
  321. Ifaces = if_pk;
  322. cp = if_name(if_pk," tx");
  323. if_pk->txproc = newproc(cp,768,if_tx,if_pk->dev,if_pk,NULL,0);
  324. free(cp);
  325. return 0;
  326. }
  327. static long
  328. access_type(
  329. int intno,
  330. int if_class,
  331. int if_type,
  332. int if_number,
  333. uint8 *type,
  334. unsigned typelen,
  335. INTERRUPT (*receiver)()
  336. ){
  337. union REGS regs;
  338. struct SREGS sregs;
  339. segread(&sregs);
  340. regs.h.dl = if_number; /* Number */
  341. sregs.ds = FP_SEG(type); /* Packet type template */
  342. regs.x.si = FP_OFF(type);
  343. regs.x.cx = typelen; /* Length of type */
  344. sregs.es = FP_SEG(receiver); /* Address of receive handler */
  345. regs.x.di = FP_OFF(receiver);
  346. regs.x.bx = if_type; /* Type */
  347. regs.h.ah = ACCESS_TYPE; /* Access_type() function */
  348. regs.h.al = if_class; /* Class */
  349. int86x(intno,&regs,&regs,&sregs);
  350. if(regs.x.cflag){
  351. Derr = regs.h.dh;
  352. return -1;
  353. } else
  354. return regs.x.ax;
  355. }
  356. static int
  357. release_type(
  358. int intno,
  359. int handle
  360. ){
  361. union REGS regs;
  362. regs.x.bx = handle;
  363. regs.h.ah = RELEASE_TYPE;
  364. int86(intno,&regs,&regs);
  365. if(regs.x.cflag){
  366. Derr = regs.h.dh;
  367. return -1;
  368. } else
  369. return 0;
  370. }
  371. static int
  372. send_pkt(
  373. int intno,
  374. uint8 *buffer,
  375. unsigned length
  376. ){
  377. union REGS regs;
  378. struct SREGS sregs;
  379. segread(&sregs);
  380. sregs.ds = FP_SEG(buffer);
  381. sregs.es = FP_SEG(buffer); /* for buggy univation pkt driver - CDY */
  382. regs.x.si = FP_OFF(buffer);
  383. regs.x.cx = length;
  384. regs.h.ah = SEND_PKT;
  385. int86x(intno,&regs,&regs,&sregs);
  386. if(regs.x.cflag){
  387. Derr = regs.h.dh;
  388. return -1;
  389. } else
  390. return 0;
  391. }
  392. static int
  393. driver_info(
  394. int intno,
  395. int handle,
  396. int *version,
  397. int *class,
  398. int *type,
  399. int *number,
  400. int *basic
  401. ){
  402. union REGS regs;
  403. regs.x.bx = handle;
  404. regs.h.ah = DRIVER_INFO;
  405. regs.h.al = 0xff;
  406. int86(intno,&regs,&regs);
  407. if(regs.x.cflag){
  408. Derr = regs.h.dh;
  409. return -1;
  410. }
  411. if(version != NULL)
  412. *version = regs.x.bx;
  413. if(class != NULL)
  414. *class = regs.h.ch;
  415. if(type != NULL)
  416. *type = regs.x.dx;
  417. if(number != NULL)
  418. *number = regs.h.cl;
  419. if(basic != NULL)
  420. *basic = regs.h.al;
  421. return 0;
  422. }
  423. static int
  424. get_address(
  425. int intno,
  426. int handle,
  427. uint8 *buf,
  428. int len
  429. ){
  430. union REGS regs;
  431. struct SREGS sregs;
  432. segread(&sregs);
  433. sregs.es = FP_SEG(buf);
  434. regs.x.di = FP_OFF(buf);
  435. regs.x.cx = len;
  436. regs.x.bx = handle;
  437. regs.h.ah = GET_ADDRESS;
  438. int86x(intno,&regs,&regs,&sregs);
  439. if(regs.x.cflag){
  440. Derr = regs.h.dh;
  441. return -1;
  442. }
  443. return 0;
  444. }
  445. static int
  446. set_rcv_mode(
  447. int intno,
  448. int handle,
  449. int mode
  450. ){
  451. union REGS regs;
  452. struct SREGS sregs;
  453. segread(&sregs);
  454. regs.x.cx = mode;
  455. regs.x.bx = handle;
  456. regs.h.ah = SET_RCV_MODE;
  457. int86x(intno,&regs,&regs,&sregs);
  458. if(regs.x.cflag){
  459. Derr = regs.h.dh;
  460. return -1;
  461. }
  462. return 0;
  463. }