PageRenderTime 49ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/kernel/ttd/ttd_comm.c

https://github.com/Prajna/mach
C | 1183 lines | 662 code | 173 blank | 348 comment | 89 complexity | 1171e0ea3129f55139c5bca6956cdbfd MD5 | raw file
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1992 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. /*
  27. * TTD Communications parsing code for the kernel ttd server.
  28. *
  29. * HISTORY:
  30. * $Log: ttd_comm.c,v $
  31. * Revision 2.2 93/05/10 23:24:28 rvb
  32. * Checkin for MK80 branch.
  33. * [93/05/10 15:05:52 grm]
  34. *
  35. * Revision 2.1.2.2 93/04/20 10:51:43 grm
  36. * Changed for use with mips and machines of both endian types.
  37. * Changed many of the types so that the same protocol will be
  38. * decodable by many machine types.
  39. * [93/04/20 grm]
  40. *
  41. * Revision 2.1.2.1 93/03/03 14:35:46 grm
  42. * Second version of code. It works.
  43. * [93/03/03 grm]
  44. *
  45. * Revision 2.1.1.10 93/01/22 15:51:24 grm
  46. * Added request pkt length checks.
  47. *
  48. * Revision 2.1.1.9 93/01/21 13:02:00 grm
  49. * Changed to ansi prototypes.
  50. *
  51. * Revision 2.1.1.8 92/10/23 21:16:53 grm
  52. * Fixed bug in kttd_valid_request so that it looks at correct
  53. * incoming packet.
  54. * [92/10/23 grm]
  55. *
  56. * Revision 2.1.1.7 92/10/08 14:27:10 grm
  57. * Now sends and receives packets.
  58. * [92/10/08 grm]
  59. *
  60. * Revision 2.1.1.6 92/10/01 15:35:50 grm
  61. * Restructuring of ttd code checkpoint.
  62. * [92/10/01 grm]
  63. *
  64. * Revision 2.1.1.5 92/09/30 13:32:31 grm
  65. * Changed for use with Mach specific kttd routines (sync and async).
  66. * Added get_request, and valid_request.
  67. * [92/09/30 grm]
  68. *
  69. * Revision 2.1.1.4 92/09/25 15:15:34 grm
  70. * checkpointing...
  71. * [92/09/25 grm]
  72. *
  73. * Revision 2.1.1.3 92/09/21 13:22:17 grm
  74. * This version uses bootp, and responds to arp requests.
  75. * [92/09/21 grm]
  76. *
  77. * Revision 2.1.1.2 92/09/15 18:27:57 grm
  78. * Checkpoint version with bootp working.
  79. *
  80. * Revision 2.1.1.1 92/09/09 14:44:07 grm
  81. * Initial checkin.
  82. *
  83. */
  84. /***********************************************************
  85. Copyright 1992 by Digital Equipment Corporation, Maynard, Massachusetts,
  86. All Rights Reserved
  87. Permission to use, copy, modify, and distribute this software and its
  88. documentation for any purpose and without fee is hereby granted, provided
  89. that the above copyright notice appear in all copies and that both that
  90. copyright notice and this permission notice appear in supporting
  91. documentation, and that the name of Digital not be used in advertising
  92. or publicity pertaining to distribution of the software without specific,
  93. written prior permission. Digital makes no representations about the
  94. suitability of this software for any purpose. It is provided "as is"
  95. without express or implied warranty.
  96. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  97. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  98. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  99. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  100. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  101. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  102. SOFTWARE.
  103. ******************************************************************/
  104. /*****************************************************/
  105. /* ttd_comm.c */
  106. /* Simple TTD/UDP/IP/ARP protocol package for lowttd */
  107. /*****************************************************/
  108. #include <device/if_ether.h>
  109. #include <device/net_status.h>
  110. #include <ttd/ttd_stub.h>
  111. #include <ttd/ttd_comm.h>
  112. #include <ttd/ttd_types.h>
  113. #include <ttd/ttd_msg.h>
  114. #include <ttd/ttd_debug.h>
  115. static struct ether_hardware_address broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  116. static struct ip_address my_ip_addr;
  117. static struct ip_address ip_broadcast = {0xff, 0xff, 0xff, 0xff};
  118. static struct ip_address ip_undefined = {0x00, 0x00, 0x00, 0x00};
  119. #define skip_pkt_header(pkt) (arp_packet_t)((natural_t)pkt + sizeof(struct packet_header))
  120. /*
  121. * My own damn byte swapping routines:
  122. */
  123. #if BYTE_MSF
  124. #else
  125. u_short netswap_2_bytes(u_short n)
  126. {
  127. u_short tmp0;
  128. tmp0 = (n << 8);
  129. tmp0 |= (n >> 8);
  130. return tmp0;
  131. }
  132. uint32 netswap_4_bytes(uint32 n)
  133. {
  134. uint32 tmp0, tmp1;
  135. tmp0 = (n << 24) | (n >> 24);
  136. tmp1 = (n & 0xff00) << 8;
  137. tmp0 |= tmp1;
  138. tmp1 = (n >> 8) & 0xff00;
  139. return tmp0 | tmp1;
  140. }
  141. #endif /* BYTE_MSF */
  142. /***************************************/
  143. /* Checksum routines */
  144. /***************************************/
  145. /*
  146. * finish_checksum converts a two's complement accumulation of
  147. * HalfWords into the one's complement checksum.
  148. */
  149. static int finish_checksum(int w)
  150. {
  151. if (w == 0)
  152. return 0xffff;
  153. while (w > 0xffff)
  154. w = (w & 0xffff) + (w >> 16);
  155. return w ^ 0xffff;
  156. }
  157. /*
  158. * checksum_ip_header is applied to an IP direct from the
  159. * network interface, before any byteswapping.
  160. * Note that this means that the addition is
  161. * performed with the bytes of each halfword
  162. * reversed, but this is OK due to the magic
  163. * nature of ones complement arithmetic!
  164. * A checksum in network order is returned.
  165. */
  166. static int checksum_ip_header(struct ip_header *ip)
  167. {
  168. half_word_t *wp;
  169. int all, i, ip_header_halfwords;
  170. all = - ip->header_checksum; /* don't count checksum field */
  171. wp = (half_word_t *) ip;
  172. ip_header_halfwords = ip->header_words * 2;
  173. for (i = 0; i < ip_header_halfwords; i++)
  174. all += wp[i];
  175. return (finish_checksum(all));
  176. }
  177. static boolean_t ip_checksum_ok(struct ip_header *ip)
  178. {
  179. int net_check;
  180. net_check = ip->header_checksum;
  181. return ((net_check == 0) || (checksum_ip_header(ip) == net_check));
  182. }
  183. static void set_ip_checksum(struct ip_header *ip)
  184. {
  185. ip->header_checksum = checksum_ip_header(ip);
  186. }
  187. static void byteswap_ip_header(struct ip_header *ip_hdr)
  188. {
  189. ip_hdr->length = netswap_2_bytes(ip_hdr->length);
  190. ip_hdr->id = netswap_2_bytes(ip_hdr->id);
  191. ip_hdr->fragment_stuff = netswap_2_bytes(ip_hdr->fragment_stuff);
  192. ip_hdr->header_checksum = netswap_2_bytes(ip_hdr->header_checksum);
  193. }
  194. /*
  195. * Use this after checking the IP header checksum.
  196. * A checksum in network order is returned.
  197. */
  198. static int checksum_udp(struct udp_header *udp,
  199. struct udp_pseudo_header pseudo_hdr)
  200. {
  201. half_word_t *wp;
  202. byte_t *bp;
  203. int all, i, udp_bytes, udp_halfwords;
  204. all = - udp->checksum; /* don't count checksum field */
  205. wp = (half_word_t *) &pseudo_hdr;
  206. for (i = 0; i < sizeof(struct udp_pseudo_header) / sizeof(half_word_t); i++)
  207. all += wp[i];
  208. udp_bytes = netswap_2_bytes(udp->length);
  209. udp_halfwords = udp_bytes / 2;
  210. wp = (half_word_t *) udp;
  211. for (i = 0; i <= udp_halfwords - 1; i++)
  212. all += wp[i];
  213. if ((udp_bytes % 2) == 1) {
  214. bp = (byte_t *) wp;
  215. all += bp[udp_bytes - 1];
  216. }
  217. return (finish_checksum (all));
  218. }
  219. static boolean_t udp_checksum_ok(struct udp_header *udp,
  220. struct udp_pseudo_header pseudo_hdr)
  221. {
  222. int net_check;
  223. net_check = udp->checksum;
  224. return ((net_check == 0) ||
  225. (checksum_udp(udp, pseudo_hdr) == net_check));
  226. }
  227. static void set_udp_checksum(struct udp_header *udp,
  228. struct udp_pseudo_header ph)
  229. {
  230. udp->checksum = checksum_udp(udp, ph);
  231. }
  232. /*****************************************/
  233. /* Simple-minded ARP Server */
  234. /*****************************************/
  235. static boolean_t eq_ip(struct ip_address a, struct ip_address b)
  236. {
  237. int i;
  238. for (i = 0; i < IP_ADDRESS_LENGTH; i++)
  239. if (a.array[i] != b.array[i])
  240. return FALSE;
  241. return TRUE;
  242. }
  243. static foocount = 10;
  244. void dump_arp_packet(struct ttd_ether_header * e, arp_packet_t p)
  245. {
  246. printf("\neh.dest %x:%x:%x:%x:%x:%x, ",
  247. e->dest.array[0],
  248. e->dest.array[1],
  249. e->dest.array[2],
  250. e->dest.array[3],
  251. e->dest.array[4],
  252. e->dest.array[5]);
  253. printf("eh.source %x:%x:%x:%x:%x:%x, ",
  254. e->source.array[0],
  255. e->source.array[1],
  256. e->source.array[2],
  257. e->source.array[3],
  258. e->source.array[4],
  259. e->source.array[4]);
  260. printf("eh.protocol = %x, ", e->protocol);
  261. printf("arp.hat %x, ", p->hardware_addr_type);
  262. printf("arp.pat %x, ", p->protocol_addr_type);
  263. printf("arp.hal %x, ", p->hardware_addr_length);
  264. printf("arp.pal %x, ", p->protocol_addr_length);
  265. printf("arp.aop %x, ", p->arp_opcode);
  266. printf("arp.sha %x:%x:%x:%x:%x:%x",
  267. p->ip.source_hardware_addr.array[0],
  268. p->ip.source_hardware_addr.array[1],
  269. p->ip.source_hardware_addr.array[2],
  270. p->ip.source_hardware_addr.array[3],
  271. p->ip.source_hardware_addr.array[4],
  272. p->ip.source_hardware_addr.array[5]);
  273. printf("arp.spa %d.%d.%d.%d, ",
  274. p->ip.source_protocol_addr.array[0],
  275. p->ip.source_protocol_addr.array[1],
  276. p->ip.source_protocol_addr.array[2],
  277. p->ip.source_protocol_addr.array[3]);
  278. printf("arp.dha %x:%x:%x:%x:%x:%x",
  279. p->ip.dest_hardware_addr.array[0],
  280. p->ip.dest_hardware_addr.array[1],
  281. p->ip.dest_hardware_addr.array[2],
  282. p->ip.dest_hardware_addr.array[3],
  283. p->ip.dest_hardware_addr.array[4],
  284. p->ip.dest_hardware_addr.array[5]);
  285. printf("arp.dpa %d.%d.%d.%d, ",
  286. p->ip.dest_protocol_addr.array[0],
  287. p->ip.dest_protocol_addr.array[1],
  288. p->ip.dest_protocol_addr.array[2],
  289. p->ip.dest_protocol_addr.array[3]);
  290. if (!foocount--)
  291. while(1);
  292. }
  293. static void handle_arp_packet(int unit,
  294. struct ttd_ether_header * ehp,
  295. struct packet_header * pkt)
  296. {
  297. arp_packet_t p;
  298. arpether_packet_t rpkt;
  299. /*
  300. * Set to point at the separate arp part of the received message
  301. */
  302. p = skip_pkt_header(pkt);
  303. /* ARP is simple; req is turned into reply and xmitted inline. */
  304. if (p->hardware_addr_type != ARPTYPE_ETHER) { /* != 0x0100 */
  305. return;
  306. }
  307. if (p->protocol_addr_type != ETHERTYPE_IP) { /* != 0x0008 */
  308. return;
  309. }
  310. if (p->hardware_addr_length != ETHER_ADDRESS_LENGTH) { /* != 0x06 */
  311. return;
  312. }
  313. if (p->protocol_addr_length != IP_ADDRESS_LENGTH) { /* != 0x04 */
  314. return;
  315. }
  316. if (p->arp_opcode != ARPOP_REQUEST) { /* != 0x0100 */
  317. return;
  318. }
  319. if (!eq_ip(p->ip.dest_protocol_addr, my_ip_addr)) {
  320. return;
  321. }
  322. /*
  323. * Fix up the reply message:
  324. */
  325. rpkt = (arpether_packet_t)ttd_reply_msg;
  326. bzero(rpkt, MIN_PACKET);
  327. rpkt->eh.dest = ehp->source;
  328. rpkt->eh.source = ttd_host_ether_id;
  329. rpkt->eh.protocol = ETHERTYPE_ARP;
  330. rpkt->arp.hardware_addr_type = ARPTYPE_ETHER;
  331. rpkt->arp.protocol_addr_type = ETHERTYPE_IP;
  332. rpkt->arp.hardware_addr_length = ETHER_ADDRESS_LENGTH;
  333. rpkt->arp.protocol_addr_length = IP_ADDRESS_LENGTH;
  334. rpkt->arp.ip.dest_protocol_addr = p->ip.source_protocol_addr;
  335. rpkt->arp.ip.dest_hardware_addr = p->ip.source_hardware_addr;
  336. rpkt->arp.ip.source_protocol_addr = my_ip_addr;
  337. rpkt->arp.ip.source_hardware_addr = ttd_host_ether_id;
  338. rpkt->arp.arp_opcode = ARPOP_REPLY;
  339. /*
  340. * Send a reply....
  341. */
  342. ttd_send_packet(ttd_device_unit, rpkt, MIN_PACKET);
  343. }
  344. /*****************************************/
  345. /* Bootp Packet Handling */
  346. /*****************************************/
  347. /*
  348. * Generate a ``random'' transaction id number. It builds it out of the
  349. * hardware ethernet id. It's not unique -- XXX
  350. */
  351. static uint32 build_xid(void)
  352. {
  353. natural_t ret;
  354. ret = ((ttd_host_ether_id.array[0] <<12) ||
  355. (ttd_host_ether_id.array[5] <<8) ||
  356. (ttd_host_ether_id.array[1] <<4) ||
  357. ttd_host_ether_id.array[4]);
  358. ret ^= ((ttd_host_ether_id.array[2] <<12) ||
  359. (ttd_host_ether_id.array[3] <<4));
  360. return ret;
  361. }
  362. void dump_ipudpbootp(char * s, sndbootp_t ptr)
  363. {
  364. recbootp_t p = (recbootp_t)&ptr->ui;
  365. bootp_t bp = (bootp_t)p->bpbuf;
  366. printf("%s",s);
  367. if (bp->bp_op == BOOTREQUEST) {
  368. printf(", bootrequest is ok\n");
  369. return;
  370. }else{
  371. printf("\n");
  372. }
  373. printf("UDP Header: source %d (%d)\n",p->ui.udp_h.source_port,
  374. ((natural_t)&p->ui.udp_h.dest_port-(natural_t)&p->ui.udp_h.source_port));
  375. printf("dest %d, (%d)\n",p->ui.udp_h.dest_port,
  376. ((natural_t)&p->ui.udp_h.length - (natural_t)&p->ui.udp_h.dest_port));
  377. printf("length %d, (%d)\n",p->ui.udp_h.length,
  378. ((natural_t)&p->ui.udp_h.checksum - (natural_t)&p->ui.udp_h.length));
  379. printf("checksum %d, (%d)\n",p->ui.udp_h.checksum,
  380. ((natural_t)&bp->bp_op - (natural_t)&p->ui.udp_h.checksum));
  381. printf("BOOTP Contents: bp_op %d, (%d)\n", bp->bp_op,
  382. ((natural_t)&bp->bp_htype - (natural_t)&bp->bp_op));
  383. printf("bp_htype %d, (%d)\n", bp->bp_htype,
  384. ((natural_t)&bp->bp_hlen - (natural_t)&bp->bp_htype));
  385. printf("bp_hlen %d, (%d)\n", bp->bp_hlen,
  386. ((natural_t)&bp->bp_hops - (natural_t)&bp->bp_hlen));
  387. printf("bp_hops %d, (%d)\n", bp->bp_hops,
  388. ((natural_t)&bp->bp_xid - (natural_t)&bp->bp_hops));
  389. printf("bp_xid %d, (%d)\n", bp->bp_xid,
  390. ((natural_t)&bp->bp_secs - (natural_t)&bp->bp_xid));
  391. printf("bp_secs %d, (%d)\n", bp->bp_secs,
  392. ((natural_t)&bp->bp_unused - (natural_t)&bp->bp_secs));
  393. printf("bp_unused %d, (%d)\n", bp->bp_unused,
  394. ((natural_t)&bp->bp_ciaddr - (natural_t)&bp->bp_unused));
  395. printf("bp_ciaddr %d.%d.%d.%d, (%d)\n",
  396. bp->bp_ciaddr.array[0],
  397. bp->bp_ciaddr.array[1],
  398. bp->bp_ciaddr.array[2],
  399. bp->bp_ciaddr.array[3],
  400. ((natural_t)&bp->bp_yiaddr - (natural_t)&bp->bp_ciaddr));
  401. printf("bp_yiaddr %d.%d.%d.%d, (%d)\n",
  402. bp->bp_yiaddr.array[0],
  403. bp->bp_yiaddr.array[1],
  404. bp->bp_yiaddr.array[2],
  405. bp->bp_yiaddr.array[3],
  406. ((natural_t)&bp->bp_siaddr - (natural_t)&bp->bp_yiaddr));
  407. printf("bp_siaddr %d.%d.%d.%d, (%d)\n",
  408. bp->bp_siaddr.array[0],
  409. bp->bp_siaddr.array[1],
  410. bp->bp_siaddr.array[2],
  411. bp->bp_siaddr.array[3],
  412. ((natural_t)&bp->bp_giaddr - (natural_t)&bp->bp_siaddr));
  413. printf("bp_giaddr %d.%d.%d.%d, (%d)\n",
  414. bp->bp_giaddr.array[0],
  415. bp->bp_giaddr.array[1],
  416. bp->bp_giaddr.array[2],
  417. bp->bp_giaddr.array[3],
  418. ((natural_t)&bp->bp_chaddr - (natural_t)&bp->bp_giaddr));
  419. printf("bp_chaddr %x:%x:%x:%x:%x:%x, (%d)\n",
  420. bp->bp_chaddr[0],
  421. bp->bp_chaddr[1],
  422. bp->bp_chaddr[2],
  423. bp->bp_chaddr[3],
  424. bp->bp_chaddr[4],
  425. bp->bp_chaddr[5],
  426. ((natural_t)&bp->bp_sname - (natural_t)&bp->bp_chaddr));
  427. while(1);
  428. }
  429. /*
  430. * Builds an ethernet packet that contains a valid bootp
  431. * request. This consists of a valid ethernet header, valid
  432. * ip header, udp header, and bootp request record.
  433. */
  434. static void build_bootp_packet(sndbootp_t buf, int size)
  435. {
  436. bootp_t bp;
  437. uint32 tmp;
  438. bp = (bootp_t)buf->bpbuf;
  439. /*
  440. * Clean out the buffer.
  441. */
  442. bzero(buf,size);
  443. /*
  444. * Set up ethernet header:
  445. */
  446. buf->eh.dest = broadcast;
  447. buf->eh.source = ttd_host_ether_id;
  448. buf->eh.protocol = ETHERTYPE_IP;
  449. /*
  450. * Set up ip header:
  451. */
  452. buf->ui.ip_h.header_checksum = 0;
  453. buf->ui.ip_h.id = 1;
  454. buf->ui.ip_h.fragment_stuff = 0;
  455. /* Don't know about these two!! XXX */
  456. buf->ui.ip_h.type_of_service = 0;
  457. buf->ui.ip_h.version = 4;
  458. buf->ui.ip_h.header_words = OUT_IP_HEADER_WORDS;
  459. buf->ui.ip_h.time_to_live = 0xff;
  460. buf->ui.ip_h.protocol = PROTOCOL_UDP;
  461. buf->ui.ip_h.source = ip_undefined;
  462. buf->ui.ip_h.dest = ip_broadcast;
  463. buf->ui.ip_h.length = sizeof(struct recbootp);
  464. /* Fix up for network byte order. */
  465. byteswap_ip_header(&buf->ui.ip_h);
  466. set_ip_checksum(&buf->ui.ip_h);
  467. /*
  468. * Set up the udp header:
  469. */
  470. buf->ui.udp_h.source_port = netswap_2_bytes(UDP_BOOTPC);
  471. buf->ui.udp_h.dest_port = netswap_2_bytes(UDP_BOOTPS);
  472. buf->ui.udp_h.length = netswap_2_bytes(sizeof(struct udp_header)+
  473. sizeof(struct bootp));
  474. buf->ui.udp_h.checksum = 0;
  475. /*
  476. * Set up bootp info:
  477. */
  478. bp->bp_op = BOOTREQUEST;
  479. bp->bp_htype = ETHER_HTYPE;
  480. bp->bp_hlen = ETHER_ADDRESS_LENGTH;
  481. tmp = netswap_4_bytes(build_xid());
  482. bp->bp_xid[0] = tmp & 0xf;
  483. bp->bp_xid[1] = (tmp & 0xf0) >> 8;
  484. bp->bp_xid[2] = (tmp & 0xf00) >> 8;
  485. bp->bp_xid[3] = (tmp & 0xf000) >> 8;
  486. bp->bp_chaddr[0] = ttd_host_ether_id.array[0];
  487. bp->bp_chaddr[1] = ttd_host_ether_id.array[1];
  488. bp->bp_chaddr[2] = ttd_host_ether_id.array[2];
  489. bp->bp_chaddr[3] = ttd_host_ether_id.array[3];
  490. bp->bp_chaddr[4] = ttd_host_ether_id.array[4];
  491. bp->bp_chaddr[5] = ttd_host_ether_id.array[5];
  492. }
  493. /*
  494. * Check an incoming message for a valid bootp reply.
  495. */
  496. static boolean_t check_bootp_reply(void)
  497. {
  498. recbootp_t rbootp;
  499. struct ttd_ether_header * ehp;
  500. bootp_t bp;
  501. uint32 tmp;
  502. /*
  503. * Set up the pointers to point at the separate ether and ip data
  504. * in the netkmsg.
  505. */
  506. ehp = (struct ttd_ether_header *)
  507. &((net_rcv_msg_t)&((ipc_kmsg_t)ttd_request_msg)->ikm_header)->header[0];
  508. rbootp = (recbootp_t)((natural_t)(&((net_rcv_msg_t)
  509. &((ipc_kmsg_t)ttd_request_msg)->ikm_header)->packet[0])
  510. +(natural_t)(sizeof(struct packet_header)));
  511. bp = (bootp_t)rbootp->bpbuf;
  512. #if DEBUG_ETHER_PACKETS
  513. printf("cBr.1 %x:%x:%x:%x:%x:%x %x:%x:%x:%x:%x:%x ",
  514. ehp->dest.array[0],
  515. ehp->dest.array[1],
  516. ehp->dest.array[2],
  517. ehp->dest.array[3],
  518. ehp->dest.array[4],
  519. ehp->dest.array[5],
  520. ehp->source.array[0],
  521. ehp->source.array[1],
  522. ehp->source.array[2],
  523. ehp->source.array[3],
  524. ehp->source.array[4],
  525. ehp->source.array[5]);
  526. #endif /* DEBUG_ETHER_PACKETS */
  527. /*
  528. * Check the ethernet header for my destination address and
  529. * the Ethernet IP protocol.
  530. */
  531. if (!ETHER_ADDRESS_EQ(&ehp->dest, &ttd_host_ether_id))
  532. return FALSE;
  533. if (ehp->protocol != ETHERTYPE_IP)
  534. return FALSE;
  535. /*
  536. * Got a packet for my machine. Check the IP for datagram packet.
  537. */
  538. if (!ip_checksum_ok(&rbootp->ui.ip_h))
  539. return FALSE;
  540. byteswap_ip_header(&rbootp->ui.ip_h);
  541. if (rbootp->ui.ip_h.protocol != PROTOCOL_UDP)
  542. return FALSE;
  543. /*
  544. * It's a UDP datagram (maybe :-))
  545. * Check for bootp udp ports, udp length, xid, etc...
  546. */
  547. if (rbootp->ui.udp_h.source_port != netswap_2_bytes(UDP_BOOTPS))
  548. return FALSE;
  549. if (rbootp->ui.udp_h.dest_port != netswap_2_bytes(UDP_BOOTPC))
  550. return FALSE;
  551. if (netswap_2_bytes(rbootp->ui.udp_h.length) <
  552. (sizeof(struct udp_header) + sizeof(struct bootp)))
  553. return FALSE;
  554. if (bp->bp_op != BOOTREPLY)
  555. return FALSE;
  556. tmp = netswap_4_bytes(build_xid());
  557. if ((bp->bp_xid[0] != tmp & 0xf) &&
  558. (bp->bp_xid[1] != (tmp & 0xf0) >> 8) &&
  559. (bp->bp_xid[2] != (tmp & 0xf00) >> 8) &&
  560. (bp->bp_xid[3] != (tmp & 0xf000) >> 8))
  561. return FALSE;
  562. if (bp->bp_htype != ETHER_HTYPE)
  563. return FALSE;
  564. if (bp->bp_hlen != ETHER_ADDRESS_LENGTH)
  565. return FALSE;
  566. my_ip_addr = bp->bp_yiaddr;
  567. return TRUE;
  568. }
  569. /*
  570. * Try to get my host ip via the bootp protocol. This routine
  571. * sends a bootp packet and then waits for a valid bootp return
  572. * call. The routine returns true upon success, false if no bootp
  573. * server responds within the timeout period.
  574. */
  575. static boolean_t do_bootp(void)
  576. {
  577. natural_t max_tries;
  578. natural_t backoff;
  579. natural_t recvd;
  580. /*
  581. * Only send BOOTPMAX_TRIES bootp queries before giving up.
  582. */
  583. for(max_tries = BOOTPMAX_TRIES, backoff = 4;
  584. max_tries;
  585. max_tries--, backoff = ((backoff < 60) ? (backoff*2) : 60)) {
  586. build_bootp_packet((sndbootp_t)ttd_request_msg, BOOTPMSG_SIZE);
  587. ttd_send_packet(ttd_device_unit, ttd_request_msg, BOOTPMSG_SIZE);
  588. for(recvd = 0;
  589. recvd < backoff;
  590. recvd++) {
  591. /*
  592. * Clean up receive buffer and get a message
  593. */
  594. bzero(ttd_request_msg, BOOTPMSG_SIZE);
  595. ttd_get_packet(ttd_device_unit);
  596. if (check_bootp_reply())
  597. return TRUE;
  598. }
  599. }
  600. return FALSE;
  601. }
  602. boolean_t ttd_ip_bootp(void)
  603. {
  604. boolean_t ret;
  605. /*
  606. * Turn on ttd so that ether drivers work with the polling routines.
  607. */
  608. printf("Looking for bootp server...");
  609. kttd_active = MAX_KTTD_ACTIVE;
  610. ret = do_bootp();
  611. kttd_active = MIN_KTTD_ACTIVE;
  612. if(ret) {
  613. printf("found bootp server, ip address = %d.%d.%d.%d\n",
  614. my_ip_addr.array[0],
  615. my_ip_addr.array[1],
  616. my_ip_addr.array[2],
  617. my_ip_addr.array[3]);
  618. }else{
  619. kttd_enabled = FALSE;
  620. printf("\ncouldn't find a bootp server.\n");
  621. }
  622. return ret;
  623. }
  624. /***************************************/
  625. /* IP Packet Handling */
  626. /***************************************/
  627. static void pseudo_header(struct ip_header *ip,
  628. struct udp_pseudo_header *pseudo_hdr)
  629. {
  630. pseudo_hdr->source = ip->source;
  631. pseudo_hdr->dest = ip->dest;
  632. pseudo_hdr->zero = 0;
  633. pseudo_hdr->protocol = ip->protocol;
  634. /* pseudo_hdr->udpLength = <set later>; -- must be in network order */
  635. }
  636. void dump_ether_header(char * mess, struct ttd_ether_header * ehp)
  637. {
  638. printf("%s dhost: %x:%x:%x:%x:%x:%x",
  639. mess,
  640. ehp->dest.array[0],
  641. ehp->dest.array[1],
  642. ehp->dest.array[2],
  643. ehp->dest.array[3],
  644. ehp->dest.array[4],
  645. ehp->dest.array[5]);
  646. printf(" shost: %x:%x:%x:%x:%x:%x",
  647. ehp->source.array[0],
  648. ehp->source.array[1],
  649. ehp->source.array[2],
  650. ehp->source.array[3],
  651. ehp->source.array[4],
  652. ehp->source.array[5]);
  653. printf(" type = %x",ehp->protocol);
  654. }
  655. /*
  656. * New routines for kttd:
  657. */
  658. /*
  659. * poll_request:
  660. *
  661. * Get a packet from the ethernet via polling.
  662. *
  663. */
  664. static void kttd_poll_request(void)
  665. {
  666. ttd_get_packet(ttd_device_unit);
  667. }
  668. static boolean_t valid_udp_packet(struct udp_packet *udp,
  669. struct udp_pseudo_header udp_phdr,
  670. natural_t udp_length,
  671. vm_offset_t *ttd_pkt)
  672. {
  673. udp_phdr.udp_length = udp->hdr.length; /* in network order */
  674. if (!udp_checksum_ok(&udp->hdr, udp_phdr))
  675. return FALSE;
  676. if (udp->hdr.dest_port != TTD_PORT) /* in network order */
  677. return FALSE;
  678. if (netswap_2_bytes(udp->hdr.length) > udp_length) {
  679. if (kttd_debug)
  680. printf("INVALID UDP Header Length!!!\n");
  681. return FALSE;
  682. }
  683. *ttd_pkt = (vm_offset_t)&udp->data[0];
  684. return TRUE;
  685. }
  686. static boolean_t valid_ip_packet(ip_packet_t *ip,
  687. natural_t ip_len,
  688. struct udp_pseudo_header *udp_phdr)
  689. {
  690. /*
  691. * Make sure checksum adds up!
  692. */
  693. if (!ip_checksum_ok (&ip->hdr))
  694. return FALSE;
  695. pseudo_header(&ip->hdr, udp_phdr); /* pseudo-header for UDP */
  696. byteswap_ip_header(&ip->hdr); /* Can't touch header fields before this! */
  697. /*
  698. * IP's length is bad, throw packet away...
  699. */
  700. if ((ip->hdr.length > ip_len) || (ip_len > MAX_ETHER_DATA)) {
  701. byteswap_ip_header(&ip->hdr);
  702. if (kttd_debug)
  703. printf("INVALID IP LENGTH!!! 0x%x:0x%x\n",
  704. ip->hdr.length, ip_len);
  705. return FALSE;
  706. }
  707. /*
  708. * TTD packets are type UDP, discard others...
  709. */
  710. if (ip->hdr.protocol != PROTOCOL_UDP) {
  711. byteswap_ip_header(&ip->hdr);
  712. return FALSE;
  713. }
  714. return TRUE;
  715. }
  716. static boolean_t valid_ether_packet(struct ttd_ether_header *ehp,
  717. struct packet_header *pkt,
  718. boolean_t handle_arp)
  719. {
  720. /*
  721. * ignore broadcast replies
  722. */
  723. if (ETHER_ADDRESS_EQ (&ehp->source, &broadcast)) {
  724. return FALSE;
  725. }
  726. /*
  727. * If arp packet then check for broadcast request.
  728. */
  729. if ((ehp->protocol == ETHERTYPE_ARP) && handle_arp) {
  730. handle_arp_packet(ttd_device_unit, ehp, pkt);
  731. return FALSE;
  732. }
  733. if (ehp->protocol != ETHERTYPE_IP) {
  734. return FALSE;
  735. }
  736. /*
  737. * IP packet, means this might be a ttd packet.
  738. *
  739. * We aren't looking for broadcast ip dest though....
  740. */
  741. if (ETHER_ADDRESS_EQ(&ehp->dest, &broadcast))
  742. return FALSE;
  743. /*
  744. * Passes the ethernet header check...
  745. */
  746. return TRUE;
  747. }
  748. /*
  749. * kttd_valid_request(request, handle_arp):
  750. *
  751. * Given a pointer to an ipc_kmsg, determine whether it is a valid kttd
  752. * request packet.
  753. *
  754. * Arp packets are handled here handle_arp is TRUE.
  755. *
  756. * If the packet is a valid KTTD packet, the procedure sets the ttd_data
  757. * paramter to point to the start of the TTD message and returns TRUE. If
  758. * it is not a valid ttd packet it returns FALSE.
  759. *
  760. */
  761. boolean_t kttd_valid_request(ipc_kmsg_t request,
  762. boolean_t handle_arp,
  763. vm_offset_t *ttd_data,
  764. natural_t *request_length)
  765. {
  766. struct ttd_ether_header *ehp;
  767. struct packet_header *pkt;
  768. ip_packet_t *ip;
  769. natural_t length;
  770. natural_t ip_hsize;
  771. struct udp_packet *udp_pkt;
  772. struct udp_pseudo_header udp_phdr;
  773. #if 1
  774. int i;
  775. u_char *ptr;
  776. #endif 1
  777. vm_offset_t ttd_pkt;
  778. /*
  779. * Check Ether packet:
  780. */
  781. ehp = (struct ttd_ether_header *)
  782. &((net_rcv_msg_t)
  783. &((ipc_kmsg_t)request)->ikm_header)->header[0];
  784. pkt = (struct packet_header *)
  785. &((net_rcv_msg_t)
  786. &((ipc_kmsg_t)request)->ikm_header)->packet[0];
  787. if (!valid_ether_packet(ehp, pkt, handle_arp))
  788. return FALSE;
  789. /*
  790. * Check IP Packet:
  791. */
  792. length = pkt->length;
  793. ip = (ip_packet_t *)skip_pkt_header(pkt);
  794. if (!valid_ip_packet(ip, length, &udp_phdr))
  795. return FALSE;
  796. /*
  797. * Check UDP Packet:
  798. */
  799. length -= sizeof(struct ip_header);
  800. ip_hsize = ip->hdr.header_words * 4;
  801. udp_pkt = (udp_packet_t) &ip->data[ip_hsize / 2];
  802. if (!valid_udp_packet(udp_pkt, udp_phdr, length, ttd_data)) {
  803. byteswap_ip_header(&ip->hdr);
  804. return FALSE;
  805. }
  806. /*
  807. * Passed all of the tests, it's a TTD packet.
  808. */
  809. /* ttd_data was set by valid_udp_packet */
  810. *request_length = (length - sizeof(struct udp_header) -
  811. sizeof(struct packet_header));
  812. #if DEBUG_ETHER_PACKETS
  813. dump_ether_header("Ether header: ", ehp);
  814. printf("\nPacket contents: ");
  815. ptr = (u_char *)ip;
  816. for (i = 0; i < 100; i++) {
  817. printf("%x:",(u_char) *ptr);
  818. ptr++;
  819. }
  820. printf("\n");
  821. #endif /* DEBUG_ETHER_PACKETS */
  822. return TRUE;
  823. }
  824. /*
  825. * kttd_get_request:
  826. *
  827. * This routines waits for a ttd request packet to arrive on the
  828. * ethernet. It does a polling input for a packet, and then checks
  829. * the packet for a valid ttd request. It loops until it receives
  830. * a valid ttd request.
  831. *
  832. * Note: this routine only called from the synchronous ttd code,
  833. * so arp requests are handled.
  834. *
  835. * We assume that the ttd driver support has been checked and is
  836. * present.
  837. */
  838. boolean_t kttd_get_request(vm_offset_t *ttd_request,
  839. natural_t *request_length)
  840. {
  841. #if VERBOSE
  842. if (kttd_debug)
  843. printf("kttd_get_request entered.\n");
  844. #endif /* VERBOSE */
  845. /*
  846. * clean it out, just to be safe.
  847. */
  848. bzero(ttd_request_msg, MAX_TTD_MSG_SIZE);
  849. for(;;) {
  850. kttd_poll_request();
  851. #if VERBOSE
  852. if (kttd_debug)
  853. printf("-");
  854. #endif /* VERBOSE */
  855. if (kttd_valid_request((ipc_kmsg_t)ttd_request_msg,
  856. TRUE,
  857. (vm_offset_t *)ttd_request,
  858. request_length))
  859. break;
  860. }
  861. return TRUE;
  862. }
  863. /*
  864. * Index into the reply.
  865. */
  866. ttd_reply_t skip_net_headers(char * ptr)
  867. {
  868. /*
  869. * Skip ether header.
  870. */
  871. ptr += sizeof (struct ttd_ether_header);
  872. /*
  873. * Skip IP header.
  874. *
  875. * This is dangerous!!! IP header length is assumed to
  876. * be constant for this to work. Make sure when we
  877. * build the reply packet that we are setting the header
  878. * words field correctly.
  879. */
  880. ptr += OUT_IP_HEADER_BYTES;
  881. /*
  882. * Skip UDP header.
  883. */
  884. ptr += sizeof (struct udp_header);
  885. return (ttd_reply_t)ptr;
  886. }
  887. /*
  888. * Wrap the old build and finish routines into one build
  889. * routine.
  890. */
  891. void complete_and_send_ttd_reply(natural_t kttd_reply_length)
  892. {
  893. struct ttd_ether_header *req_ether_header;
  894. struct packet_header *req_ether_pkt;
  895. struct ttd_ether_header *rpy_ether_header;
  896. struct ip_header *req_ip_header;
  897. struct udp_header *req_udp_header;
  898. struct udp_header *rpy_udp_header;
  899. struct ip_header *rpy_ip_header;
  900. natural_t tmp_length;
  901. struct udp_pseudo_header uph;
  902. ipc_kmsg_t tmp_kmsg;
  903. tmp_kmsg = (ipc_kmsg_t)((kttd_current_kmsg == (ipc_kmsg_t)NULL) ?
  904. ttd_request_msg :
  905. kttd_current_kmsg);
  906. /*
  907. * Build the ethernet part of the reply.
  908. */
  909. req_ether_header = (struct ttd_ether_header *)
  910. &((net_rcv_msg_t)&(tmp_kmsg)->ikm_header)->header[0];
  911. req_ether_pkt = (struct packet_header *)
  912. &((net_rcv_msg_t)&(tmp_kmsg)->ikm_header)->packet[0];
  913. /*
  914. * The ttd_reply_msg is just the ether/ip/udp/ttd, it doesn't
  915. * have the kmsg header junk that the ttd_request_msg has.
  916. */
  917. rpy_ether_header = (struct ttd_ether_header *)ttd_reply_msg;
  918. rpy_ether_header->source = req_ether_header->dest;
  919. rpy_ether_header->dest = req_ether_header->source;
  920. rpy_ether_header->protocol = req_ether_header->protocol;
  921. /*
  922. * Partially build the IP header.
  923. *
  924. * Note: Everything at this point is NOT in network order.
  925. * The finish_ttd_build procedure must insert the
  926. * correct length, byteswap the reply header and
  927. * generate the checksum and insert it.
  928. */
  929. req_ip_header = (struct ip_header *)skip_pkt_header(req_ether_pkt);
  930. rpy_ip_header = (struct ip_header *)((natural_t)rpy_ether_header +
  931. sizeof (struct ttd_ether_header));
  932. rpy_ip_header->header_words = OUT_IP_HEADER_WORDS;
  933. rpy_ip_header->version = req_ip_header->version;
  934. rpy_ip_header->type_of_service = req_ip_header->type_of_service;
  935. /* rpy_ip_header->length = <set later>; */
  936. rpy_ip_header->fragment_stuff = 0;
  937. rpy_ip_header->id = 0;
  938. /* rpy_ip_header->header_checksum = <set later>; */
  939. rpy_ip_header->protocol = req_ip_header->protocol;
  940. rpy_ip_header->time_to_live = 255;
  941. rpy_ip_header->source = req_ip_header->dest;
  942. rpy_ip_header->dest = req_ip_header->source;
  943. /*
  944. * Partially build the UDP header.
  945. *
  946. * Note: Same problem here as the IP layer. We will still need
  947. * to set the length in the finish_ttd_build section along
  948. * with the checksum (if not using zero).
  949. */
  950. req_udp_header = (struct udp_header *)((natural_t)req_ip_header +
  951. ((natural_t)req_ip_header->header_words * 4));
  952. rpy_udp_header = (struct udp_header *)((natural_t)rpy_ip_header +
  953. OUT_IP_HEADER_BYTES);
  954. rpy_udp_header->source_port = req_udp_header->dest_port;
  955. rpy_udp_header->dest_port = req_udp_header->source_port;
  956. /* rpy_udp_header->length = <set later>; */
  957. /* rpy_udp_header->checksum = <set later>; */
  958. /*
  959. * Sanity check. Make sure that the calculated ttd_reply_msg
  960. * is the same one we just came up with!!!
  961. */
  962. if (kttd_debug && ((natural_t) skip_net_headers(ttd_reply_msg) !=
  963. ((natural_t)rpy_udp_header + (sizeof(struct udp_header))))) {
  964. printf("TTDComm.c: Woah!!! ttd_reply_msg is skewed!!\n");
  965. }
  966. #if VERBOSE
  967. if (kttd_debug)
  968. printf("build_partial: ttd_reply should start at: 0x%x, ttd_kmsg 0x%x\n",
  969. (natural_t)rpy_udp_header + sizeof(struct udp_header),
  970. ttd_reply_msg);
  971. #endif /* VERBOSE */
  972. /*
  973. * Fix up UDP length and checksum:
  974. */
  975. tmp_length = kttd_reply_length + sizeof(struct udp_header);
  976. rpy_udp_header->length = netswap_2_bytes(tmp_length);
  977. uph.source = rpy_ip_header->source;
  978. uph.dest = rpy_ip_header->dest;
  979. uph.zero = 0;
  980. uph.protocol = rpy_ip_header->protocol;
  981. uph.udp_length = rpy_udp_header->length;
  982. set_udp_checksum(rpy_udp_header, uph);
  983. /*
  984. * Fix up IP length and checksum:
  985. */
  986. tmp_length += OUT_IP_HEADER_BYTES;
  987. rpy_ip_header->length = tmp_length;
  988. byteswap_ip_header(rpy_ip_header);
  989. set_ip_checksum(rpy_ip_header);
  990. #if DEBUG_ETHER_PACKETS
  991. if (kttd_debug) {
  992. int i;
  993. u_char * ptr;
  994. ptr = (u_char *)ttd_reply_msg;
  995. for (i = 0; i< 100; i++)
  996. printf("%x: ", *ptr++);
  997. printf("\nlength = %d",tmp_length);
  998. }
  999. #endif /* DEBUG_ETHER_PACKETS */
  1000. /*
  1001. * We've built it, let's send it off!!!
  1002. */
  1003. ttd_send_packet(ttd_device_unit, ttd_reply_msg,
  1004. ((MIN_PACKET > tmp_length + sizeof(struct ttd_ether_header)) ?
  1005. MIN_PACKET : tmp_length + sizeof(struct ttd_ether_header)));
  1006. }