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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "proc.h"
  8. #include "iface.h"
  9. #include "ip.h"
  10. #include "icmp.h"
  11. #include "netuser.h"
  12. #include "ax25.h"
  13. #include "enet.h"
  14. #include "pktdrvr.h"
  15. #include "cmdparse.h"
  16. #include "commands.h"
  17. #include "trace.h"
  18. static void showiface(struct iface *ifp);
  19. static int mask2width(int32 mask);
  20. static int ifipaddr(int argc,char *argv[],void *p);
  21. static int iflinkadr(int argc,char *argv[],void *p);
  22. static int ifbroad(int argc,char *argv[],void *p);
  23. static int ifnetmsk(int argc,char *argv[],void *p);
  24. static int ifrxbuf(int argc,char *argv[],void *p);
  25. static int ifmtu(int argc,char *argv[],void *p);
  26. static int ifforw(int argc,char *argv[],void *p);
  27. static int ifencap(int argc,char *argv[],void *p);
  28. static int iftxqlen(int argc,char *argv[],void *p);
  29. /* Interface list header */
  30. struct iface *Ifaces = &Loopback;
  31. /* Loopback pseudo-interface */
  32. struct iface Loopback = {
  33. &Encap, /* Link to next entry */
  34. "loopback", /* name */
  35. 0x7f000001L, /* addr 127.0.0.1 */
  36. 0xffffffffL, /* broadcast 255.255.255.255 */
  37. 0xffffffffL, /* netmask 255.255.255.255 */
  38. MAXINT16, /* mtu No limit */
  39. 0, /* trace */
  40. NULL, /* trfp */
  41. NULL, /* forw */
  42. NULL, /* rxproc */
  43. NULL, /* txproc */
  44. NULL, /* supv */
  45. NULL, /* outq */
  46. 0, /* outlim */
  47. 0, /* txbusy */
  48. NULL, /* dstate */
  49. NULL, /* dtickle */
  50. NULL, /* dstatus */
  51. 0, /* dev */
  52. NULL, /* (*ioctl) */
  53. NULL, /* (*iostatus) */
  54. NULL, /* (*stop) */
  55. NULL, /* hwaddr */
  56. NULL, /* extension */
  57. 0, /* xdev */
  58. &Iftypes[0], /* iftype */
  59. NULL, /* (*send) */
  60. NULL, /* (*output) */
  61. NULL, /* (*raw) */
  62. NULL, /* (*status) */
  63. NULL, /* (*discard) */
  64. NULL, /* (*echo) */
  65. 0, /* ipsndcnt */
  66. 0, /* rawsndcnt */
  67. 0, /* iprecvcnt */
  68. 0, /* rawrcvcnt */
  69. 0, /* lastsent */
  70. 0, /* lastrecv */
  71. };
  72. /* Encapsulation pseudo-interface */
  73. struct iface Encap = {
  74. NULL,
  75. "encap", /* name */
  76. INADDR_ANY, /* addr 0.0.0.0 */
  77. 0xffffffffL, /* broadcast 255.255.255.255 */
  78. 0xffffffffL, /* netmask 255.255.255.255 */
  79. MAXINT16, /* mtu No limit */
  80. 0, /* trace */
  81. NULL, /* trfp */
  82. NULL, /* forw */
  83. NULL, /* rxproc */
  84. NULL, /* txproc */
  85. NULL, /* supv */
  86. NULL, /* outq */
  87. 0, /* outlim */
  88. 0, /* txbusy */
  89. NULL, /* dstate */
  90. NULL, /* dtickle */
  91. NULL, /* dstatus */
  92. 0, /* dev */
  93. NULL, /* (*ioctl) */
  94. NULL, /* (*iostatus) */
  95. NULL, /* (*stop) */
  96. NULL, /* hwaddr */
  97. NULL, /* extension */
  98. 0, /* xdev */
  99. &Iftypes[0], /* iftype */
  100. ip_encap, /* (*send) */
  101. NULL, /* (*output) */
  102. NULL, /* (*raw) */
  103. NULL, /* (*status) */
  104. NULL, /* (*discard) */
  105. NULL, /* (*echo) */
  106. 0, /* ipsndcnt */
  107. 0, /* rawsndcnt */
  108. 0, /* iprecvcnt */
  109. 0, /* rawrcvcnt */
  110. 0, /* lastsent */
  111. 0, /* lastrecv */
  112. };
  113. char Noipaddr[] = "IP address field missing, and ip address not setn";
  114. struct cmds Ifcmds[] = {
  115. "broadcast", ifbroad, 0, 2, NULL,
  116. "encapsulation", ifencap, 0, 2, NULL,
  117. "forward", ifforw, 0, 2, NULL,
  118. "ipaddress", ifipaddr, 0, 2, NULL,
  119. "linkaddress", iflinkadr, 0, 2, NULL,
  120. "mtu", ifmtu, 0, 2, NULL,
  121. "netmask", ifnetmsk, 0, 2, NULL,
  122. "txqlen", iftxqlen, 0, 2, NULL,
  123. "rxbuf", ifrxbuf, 0, 2, NULL,
  124. NULL,
  125. };
  126. /*
  127.  * General purpose interface transmit task, one for each device that can
  128.  * send IP datagrams. It waits on the interface's IP output queue (outq),
  129.  * extracts IP datagrams placed there in priority order by ip_route(),
  130.  * and sends them to the device's send routine.
  131.  */
  132. void
  133. if_tx(int dev,void *arg1,void *unused)
  134. {
  135. struct mbuf *bp; /* Buffer to send */
  136. struct iface *iface; /* Pointer to interface control block */
  137. struct qhdr qhdr;
  138. iface = arg1;
  139. for(;;){
  140. while(iface->outq == NULL)
  141. kwait(&iface->outq);
  142. iface->txbusy = 1;
  143. bp = dequeue(&iface->outq);
  144. pullup(&bp,&qhdr,sizeof(qhdr));
  145. if(iface->dtickle != NULL && (*iface->dtickle)(iface) == -1){
  146. #ifdef notdef /* Confuses some non-compliant hosts */
  147. struct ip ip;
  148. /* Link redial failed; bounce with unreachable */
  149. ntohip(&ip,&bp);
  150. icmp_output(&ip,bp,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,
  151.  NULL);
  152. #endif
  153. free_p(&bp);
  154. } else {
  155. (*iface->send)(&bp,iface,qhdr.gateway,qhdr.tos);
  156. }
  157. iface->txbusy = 0;
  158. /* Let other tasks run, just in case send didn't block */
  159. kwait(NULL);
  160. }
  161. }
  162. /* Process packets in the Hopper */
  163. void
  164. network(int i,void *v1,void *v2)
  165. {
  166. struct mbuf *bp;
  167. char i_state;
  168. struct iftype *ift;
  169. struct iface *ifp;
  170. loop:
  171. for(;;){
  172. i_state = dirps();
  173. bp = Hopper;
  174. if(bp != NULL){
  175. bp = dequeue(&Hopper);
  176. restore(i_state);
  177. break;
  178. }
  179. restore(i_state);
  180. kwait(&Hopper);
  181. }
  182. /* Process the input packet */
  183. pullup(&bp,&ifp,sizeof(ifp));
  184. if(ifp != NULL){
  185. ifp->rawrecvcnt++;
  186. ifp->lastrecv = secclock();
  187. ift = ifp->iftype;
  188. } else {
  189. ift = &Iftypes[0];
  190. }
  191. dump(ifp,IF_TRACE_IN,bp);
  192. if(ift->rcvf != NULL)
  193. (*ift->rcvf)(ifp,&bp);
  194. else
  195. free_p(&bp); /* Nowhere to send it */
  196. /* Let everything else run - this keeps the system from wedging
  197.  * when we're hit by a big burst of packets
  198.  */
  199. kwait(NULL);
  200. goto loop;
  201. }
  202. /* put mbuf into Hopper for network task
  203.  * returns 0 if OK
  204.  */
  205. int
  206. net_route(struct iface *ifp,struct mbuf **bpp)
  207. {
  208. pushdown(bpp,&ifp,sizeof(ifp));
  209. enqueue(&Hopper,bpp);
  210. return 0;
  211. }
  212. /* Null send and output routines for interfaces without link level protocols */
  213. int
  214. nu_send(struct mbuf **bpp,struct iface *ifp,int32 gateway,uint8 tos)
  215. {
  216. return (*ifp->raw)(ifp,bpp);
  217. }
  218. int
  219. nu_output(struct iface *ifp,uint8 *dest,uint8 *src,uint16 type,struct mbuf **bpp)
  220. {
  221. return (*ifp->raw)(ifp,bpp);
  222. }
  223. /* Set interface parameters */
  224. int
  225. doifconfig(int argc,char *argv[],void *p)
  226. {
  227. struct iface *ifp;
  228. int i;
  229. if(argc < 2){
  230. for(ifp = Ifaces;ifp != NULL;ifp = ifp->next)
  231. showiface(ifp);
  232. return 0;
  233. }
  234. if((ifp = if_lookup(argv[1])) == NULL){
  235. printf("Interface %s unknownn",argv[1]);
  236. return 1;
  237. }
  238. if(argc == 2){
  239. showiface(ifp);
  240. if(ifp->show != NULL){
  241. (*ifp->show)(ifp);
  242. }
  243. return 0;
  244. }
  245. if(argc == 3){
  246. printf("Argument missingn");
  247. return 1;
  248. }
  249. for(i=2;i<argc-1;i+=2)
  250. subcmd(Ifcmds,3,&argv[i-1],ifp);
  251. return 0;
  252. }
  253. /* Set interface IP address */
  254. static int
  255. ifipaddr(int argc,char *argv[],void *p)
  256. {
  257. struct iface *ifp = p;
  258. ifp->addr = resolve(argv[1]);
  259. return 0;
  260. }
  261. /* Set link (hardware) address */
  262. static int
  263. iflinkadr(int argc,char *argv[],void *p)
  264. {
  265. struct iface *ifp = p;
  266. if(ifp->iftype == NULL || ifp->iftype->scan == NULL){
  267. printf("Can't set link addressn");
  268. return 1;
  269. }
  270. if(ifp->hwaddr != NULL)
  271. free(ifp->hwaddr);
  272. ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  273. (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  274. return 0;
  275. }
  276. /* Set interface broadcast address. This is actually done
  277.  * by installing a private entry in the routing table.
  278.  */
  279. static int
  280. ifbroad(int argc,char *argv[],void *p)
  281. {
  282. struct iface *ifp = p;
  283. struct route *rp;
  284. rp = rt_blookup(ifp->broadcast,32);
  285. if(rp != NULL && rp->iface == ifp)
  286. rt_drop(ifp->broadcast,32);
  287. ifp->broadcast = resolve(argv[1]);
  288. rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  289. return 0;
  290. }
  291. /* Set the network mask. This is actually done by installing
  292.  * a routing entry.
  293.  */
  294. static int
  295. ifnetmsk(int argc,char *argv[],void *p)
  296. {
  297. struct iface *ifp = p;
  298. struct route *rp;
  299. /* Remove old entry if it exists */
  300. rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  301. if(rp != NULL)
  302. rt_drop(rp->target,rp->bits);
  303. ifp->netmask = htol(argv[1]);
  304. rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  305. return 0;
  306. }
  307. /* Command to set interface encapsulation mode */
  308. static int
  309. ifencap(int argc,char *argv[],void *p)
  310. {
  311. struct iface *ifp = p;
  312. if(setencap(ifp,argv[1]) != 0){
  313. printf("Encapsulation mode '%s' unknownn",argv[1]);
  314. return 1;
  315. }
  316. return 0;
  317. }
  318. /* Function to set encapsulation mode */
  319. int
  320. setencap(struct iface *ifp,char *mode)
  321. {
  322. struct iftype *ift;
  323. for(ift = &Iftypes[0];ift->name != NULL;ift++)
  324. if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  325. break;
  326. if(ift->name == NULL)
  327. return -1;
  328. if(ifp != NULL){
  329. ifp->iftype = ift;
  330. ifp->send = ift->send;
  331. ifp->output = ift->output;
  332. }
  333. return 0;
  334. }
  335. /* Set interface receive buffer size */
  336. static int
  337. ifrxbuf(int argc,char *argv[],void *p)
  338. {
  339. return 0; /* To be written */
  340. }
  341. /* Set interface Maximum Transmission Unit */
  342. static int
  343. ifmtu(int argc,char *argv[],void *p)
  344. {
  345. struct iface *ifp = p;
  346. ifp->mtu = atoi(argv[1]);
  347. return 0;
  348. }
  349. /* Set interface forwarding */
  350. static int
  351. ifforw(int argc,char *argv[],void *p)
  352. {
  353. struct iface *ifp = p;
  354. ifp->forw = if_lookup(argv[1]);
  355. if(ifp->forw == ifp)
  356. ifp->forw = NULL;
  357. return 0;
  358. }
  359. /* Display the parameters for a specified interface */
  360. static void
  361. showiface(struct iface *ifp)
  362. {
  363. char tmp[25];
  364. printf("%-10s IP addr %s MTU %u Link encap %sn",ifp->name,
  365.  inet_ntoa(ifp->addr),(int)ifp->mtu,
  366.  ifp->iftype != NULL ? ifp->iftype->name : "not set");
  367. if(ifp->iftype != NULL && ifp->iftype->format != NULL && ifp->hwaddr != NULL){
  368. printf("           Link addr %sn",
  369.  (*ifp->iftype->format)(tmp,ifp->hwaddr));
  370. }
  371. printf("           trace 0x%x netmask 0x%08lx broadcast %sn",
  372. ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  373. if(ifp->forw != NULL)
  374. printf("           output forward to %sn",ifp->forw->name);
  375. printf("           sent: ip %lu tot %lu idle %s qlen %u",
  376.  ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent),
  377. len_q(ifp->outq));
  378. if(ifp->outlim != 0)
  379. printf("/%u",ifp->outlim);
  380. if(ifp->txbusy)
  381. printf(" BUSY");
  382. printf("n");
  383. printf("           recv: ip %lu tot %lu idle %sn",
  384.  ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  385. }
  386. /* Command to detach an interface */
  387. int
  388. dodetach(int argc,char *argv[],void *p)
  389. {
  390. register struct iface *ifp;
  391. if((ifp = if_lookup(argv[1])) == NULL){
  392. printf("Interface %s unknownn",argv[1]);
  393. return 1;
  394. }
  395. if(if_detach(ifp) == -1)
  396. printf("Can't detach loopback or encap interfacen");
  397. return 0;
  398. }
  399. /* Detach a specified interface */
  400. int
  401. if_detach(struct iface *ifp)
  402. {
  403. struct iface *iftmp;
  404. struct route *rp,*rptmp;
  405. int i,j;
  406. if(ifp == &Loopback || ifp == &Encap)
  407. return -1;
  408. /* Drop all routes that point to this interface */
  409. if(R_default.iface == ifp)
  410. rt_drop(0L,0); /* Drop default route */
  411. for(i=0;i<HASHMOD;i++){
  412. for(j=0;j<32;j++){
  413. for(rp = Routes[j][i];rp != NULL;rp = rptmp){
  414. /* Save next pointer in case we delete this entry */
  415. rptmp = rp->next;
  416. if(rp->iface == ifp)
  417. rt_drop(rp->target,rp->bits);
  418. }
  419. }
  420. }
  421. /* Unforward any other interfaces forwarding to this one */
  422. for(iftmp = Ifaces;iftmp != NULL;iftmp = iftmp->next){
  423. if(iftmp->forw == ifp)
  424. iftmp->forw = NULL;
  425. }
  426. /* Call device shutdown routine, if any */
  427. if(ifp->stop != NULL)
  428. (*ifp->stop)(ifp);
  429. killproc(ifp->rxproc);
  430. killproc(ifp->txproc);
  431. killproc(ifp->supv);
  432. /* Free allocated memory associated with this interface */
  433. if(ifp->name != NULL)
  434. free(ifp->name);
  435. if(ifp->hwaddr != NULL)
  436. free(ifp->hwaddr);
  437. /* Remove from interface list */
  438. if(ifp == Ifaces){
  439. Ifaces = ifp->next;
  440. } else {
  441. /* Search for entry just before this one
  442.  * (necessary because list is only singly-linked.)
  443.  */
  444. for(iftmp = Ifaces;iftmp != NULL ;iftmp = iftmp->next)
  445. if(iftmp->next == ifp)
  446. break;
  447. if(iftmp != NULL && iftmp->next == ifp)
  448. iftmp->next = ifp->next;
  449. }
  450. /* Finally free the structure itself */
  451. free(ifp);
  452. return 0;
  453. }
  454. static int
  455. iftxqlen(int argc,char *argv[],void *p)
  456. {
  457. struct iface *ifp = p;
  458. setint(&ifp->outlim,"TX queue limit",argc,argv);
  459. return 0;
  460. }
  461. /* Given the ascii name of an interface, return a pointer to the structure,
  462.  * or NULL if it doesn't exist
  463.  */
  464. struct iface *
  465. if_lookup(char *name)
  466. {
  467. register struct iface *ifp;
  468. for(ifp = Ifaces; ifp != NULL; ifp = ifp->next)
  469. if(strcmp(ifp->name,name) == 0)
  470. break;
  471. return ifp;
  472. }
  473. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  474.  * NULL otherwise.
  475.  * This is used to tell if an incoming IP datagram is for us, or if it
  476.  * has to be routed.
  477.  */
  478. struct iface *
  479. ismyaddr(int32 addr)
  480. {
  481. register struct iface *ifp;
  482. if(addr == INADDR_ANY)
  483. return &Loopback;
  484. for(ifp = Ifaces; ifp != NULL; ifp = ifp->next)
  485. if(addr == ifp->addr)
  486. break;
  487. return ifp;
  488. }
  489. /* Given a network mask, return the number of contiguous 1-bits starting
  490.  * from the most significant bit.
  491.  */
  492. static int
  493. mask2width(int32 mask)
  494. {
  495. int width,i;
  496. width = 0;
  497. for(i = 31;i >= 0;i--){
  498. if(!(mask & (1L << i)))
  499. break;
  500. width++;
  501. }
  502. return width;
  503. }
  504. /* return buffer with name + comment */
  505. char *
  506. if_name(struct iface *ifp,char *comment)
  507. {
  508. char *result;
  509. result = mallocw(strlen(ifp->name) + strlen(comment) + 1);
  510. strcpy(result,ifp->name);
  511. strcat(result,comment);
  512. return result;
  513. }
  514. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  515. int
  516. bitbucket(struct iface *ifp,struct mbuf **bpp)
  517. {
  518. free_p(bpp);
  519. return 0;
  520. }
  521. /* 
  522.  * dial <iface> <seconds> [device dependent args] (begin autodialing)
  523.  * dial <iface> 0 (stop autodialing) 
  524.  * dial <iface> (display status)
  525.  */
  526. int
  527. dodialer(int argc,char *argv[],void *p)
  528. {
  529. struct iface *ifp;
  530. int32 timeout;
  531. if((ifp = if_lookup(argv[1])) == NULL){
  532. printf("Interface %s unknownn",argv[1]);
  533. return 1;
  534. }
  535. if(argc < 3){
  536. if(ifp->iftype->dstat != NULL)
  537. (*ifp->iftype->dstat)(ifp);
  538. return 0;
  539. }
  540. if(ifp->iftype->dinit == NULL){
  541. printf("Dialing not supported on %sn",argv[1]);
  542. return 1;
  543. }
  544. timeout = atol(argv[2]) * 1000L;
  545. return (*ifp->iftype->dinit)(ifp,timeout,argc-3,argv+3);
  546. }