remove /usr/include dependencies
[unix-history] / usr / src / sys / deprecated / netimp / if_imp.c
CommitLineData
f4d55810 1/* if_imp.c 4.48 83/02/10 */
6c73ade6
BJ
2
3#include "imp.h"
4#if NIMP > 0
5/*
72e4f44e 6 * ARPANET IMP interface driver.
6c73ade6
BJ
7 *
8 * The IMP-host protocol is handled here, leaving
9 * hardware specifics to the lower level interface driver.
10 */
961945a8
SL
11#include "../machine/pte.h"
12
6c73ade6
BJ
13#include "../h/param.h"
14#include "../h/systm.h"
15#include "../h/mbuf.h"
6c73ade6
BJ
16#include "../h/buf.h"
17#include "../h/protosw.h"
18#include "../h/socket.h"
6c73ade6 19#include "../h/vmmac.h"
44afc493
SL
20#include "../h/time.h"
21#include "../h/kernel.h"
f4d55810 22#include "../h/errno.h"
6e7edb25
BJ
23
24#include "../vax/cpu.h"
25#include "../vax/mtpr.h"
39d536e6
BJ
26#include "../vaxuba/ubareg.h"
27#include "../vaxuba/ubavar.h"
6e7edb25 28
6c73ade6 29#include "../net/if.h"
6e7edb25 30#include "../net/route.h"
f4d55810 31
5e3649c6 32#include "../net/netisr.h"
6e7edb25
BJ
33#include "../netinet/in.h"
34#include "../netinet/in_systm.h"
35#include "../netinet/ip.h"
36#include "../netinet/ip_var.h"
b690198c 37/* define IMPLEADERS here to get leader printing code */
5e3649c6
BJ
38#include "../netimp/if_imp.h"
39#include "../netimp/if_imphost.h"
6c73ade6
BJ
40
41/*
42 * IMP software status per interface.
43 * (partially shared with the hardware specific module)
44 *
45 * Each interface is referenced by a network interface structure,
46 * imp_if, which the routing code uses to locate the interface.
47 * This structure contains the output queue for the interface, its
48 * address, ... IMP specific structures used in connecting the
49 * IMP software modules to the hardware specific interface routines
a2cd4df7
BJ
50 * are stored here. The common structures are made visible to the
51 * interface driver by passing a pointer to the hardware routine
52 * at "attach" time.
6c73ade6
BJ
53 *
54 * NOTE: imp_if and imp_cb are assumed adjacent in hardware code.
55 */
56struct imp_softc {
57 struct ifnet imp_if; /* network visible interface */
58 struct impcb imp_cb; /* hooks to hardware module */
59 u_char imp_state; /* current state of IMP */
60 char imp_dropcnt; /* used during initialization */
6c73ade6
BJ
61} imp_softc[NIMP];
62
63/*
64 * Messages from IMP regarding why
65 * it's going down.
66 */
e33b5b1a 67static char *impmessage[] = {
6c73ade6
BJ
68 "in 30 seconds",
69 "for hardware PM",
70 "to reload software",
71 "for emergency reset"
72};
73
a2cd4df7
BJ
74int impdown(), impinit(), impoutput();
75
6c73ade6
BJ
76/*
77 * IMP attach routine. Called from hardware device attach routine
78 * at configuration time with a pointer to the UNIBUS device structure.
79 * Sets up local state and returns pointer to base of ifnet+impcb
80 * structures. This is then used by the device's attach routine
81 * set up its back pointers.
82 */
30c36259 83impattach(ui, reset)
6c73ade6 84 struct uba_device *ui;
30c36259 85 int (*reset)();
6c73ade6
BJ
86{
87 struct imp_softc *sc = &imp_softc[ui->ui_unit];
88 register struct ifnet *ifp = &sc->imp_if;
ee787340 89 struct sockaddr_in *sin;
6c73ade6 90
6c73ade6
BJ
91 /* UNIT COULD BE AMBIGUOUS */
92 ifp->if_unit = ui->ui_unit;
93 ifp->if_name = "imp";
e431883e 94 ifp->if_mtu = IMPMTU - sizeof(struct imp_leader);
6c73ade6 95 ifp->if_net = ui->ui_flags;
ac697091 96 ifp->if_reset = reset;
aee8ddf8 97 /* the host and imp fields will be filled in by the imp */
ee787340
SL
98 sin = (struct sockaddr_in *)&ifp->if_addr;
99 sin->sin_family = AF_INET;
100 sin->sin_addr = if_makeaddr(ifp->if_net, 0);
a2cd4df7
BJ
101 ifp->if_init = impinit;
102 ifp->if_output = impoutput;
103 /* reset is handled at the hardware level */
6c73ade6 104 if_attach(ifp);
6c73ade6
BJ
105 return ((int)&sc->imp_if);
106}
107
108/*
109 * IMP initialization routine: call hardware module to
110 * setup UNIBUS resources, init state and get ready for
111 * NOOPs the IMP should send us, and that we want to drop.
112 */
113impinit(unit)
114 int unit;
115{
98b6195e 116 int s = splimp();
6c73ade6
BJ
117 register struct imp_softc *sc = &imp_softc[unit];
118
a2cd4df7
BJ
119 if ((*sc->imp_cb.ic_init)(unit) == 0) {
120 sc->imp_state = IMPS_DOWN;
ee787340 121 sc->imp_if.if_flags &= ~IFF_UP;
98b6195e 122 splx(s);
a2cd4df7
BJ
123 return;
124 }
6c73ade6 125 sc->imp_state = IMPS_INIT;
a2cd4df7 126 impnoops(sc);
98b6195e 127 splx(s);
6c73ade6
BJ
128}
129
130struct sockproto impproto = { PF_IMPLINK };
faad37c0
SL
131struct sockaddr_in impdst = { AF_IMPLINK };
132struct sockaddr_in impsrc = { AF_IMPLINK };
b690198c 133#ifdef IMPLEADERS
7dfb87a5 134int impprintfs = 0;
b690198c 135#endif
6c73ade6
BJ
136
137/*
138 * ARPAnet 1822 input routine.
139 * Called from hardware input interrupt routine to handle 1822
140 * IMP-host messages. Type 0 messages (non-control) are
141 * passed to higher level protocol processors on the basis
142 * of link number. Other type messages (control) are handled here.
143 */
a2cd4df7 144impinput(unit, m)
6c73ade6 145 int unit;
a2cd4df7 146 register struct mbuf *m;
6c73ade6 147{
6c73ade6
BJ
148 register struct imp_leader *ip;
149 register struct imp_softc *sc = &imp_softc[unit];
150 register struct host *hp;
151 register struct ifqueue *inq;
a2cd4df7 152 struct control_leader *cp;
6c73ade6 153 struct in_addr addr;
e33b5b1a 154 struct mbuf *next;
ee787340 155 struct sockaddr_in *sin;
6c73ade6 156
34c22ab5 157 /* verify leader length. */
a2cd4df7
BJ
158 if (m->m_len < sizeof(struct control_leader) &&
159 (m = m_pullup(m, sizeof(struct control_leader))) == 0)
160 return;
161 cp = mtod(m, struct control_leader *);
162 if (cp->dl_mtype == IMPTYPE_DATA)
163 if (m->m_len < sizeof(struct imp_leader) &&
164 (m = m_pullup(m, sizeof(struct imp_leader))) == 0)
165 return;
6c73ade6 166 ip = mtod(m, struct imp_leader *);
b690198c 167#ifdef IMPLEADERS
7dfb87a5
SL
168 if (impprintfs)
169 printleader("impinput", ip);
b690198c 170#endif
6c73ade6 171
34c22ab5 172 /* check leader type */
a2cd4df7
BJ
173 if (ip->il_format != IMP_NFF) {
174 sc->imp_if.if_collisions++; /* XXX */
6c73ade6 175 goto drop;
a2cd4df7 176 }
6c73ade6 177
ba45553a 178 if (ip->il_mtype != IMPTYPE_DATA) {
41e530c7 179#ifdef notdef
a2cd4df7 180 addr.s_net = ip->il_network;
41e530c7 181#else
ba45553a 182 addr.s_net = sc->imp_if.if_net;
41e530c7 183#endif
a2cd4df7
BJ
184 addr.s_imp = ip->il_imp;
185 addr.s_host = ip->il_host;
6c73ade6 186 }
6c73ade6
BJ
187 switch (ip->il_mtype) {
188
6c73ade6 189 case IMPTYPE_DATA:
6c73ade6
BJ
190 break;
191
192 /*
193 * IMP leader error. Reset the IMP and discard the packet.
194 */
195 case IMPTYPE_BADLEADER:
a0b7c7fb
SL
196 /*
197 * According to 1822 document, this message
198 * will be generated in response to the
199 * first noop sent to the IMP after
200 * the host resets the IMP interface.
201 */
a2cd4df7 202 if (sc->imp_state != IMPS_INIT) {
e33b5b1a 203 impmsg(sc, "leader error");
72e4f44e 204 hostreset(sc->imp_if.if_net);
a0b7c7fb
SL
205 impnoops(sc);
206 }
72e4f44e 207 goto drop;
6c73ade6
BJ
208
209 /*
210 * IMP going down. Print message, and if not immediate,
211 * set off a timer to insure things will be reset at the
212 * appropriate time.
213 */
214 case IMPTYPE_DOWN:
f32a85bb 215 if (sc->imp_state < IMPS_INIT)
47e51140 216 goto drop;
6c73ade6
BJ
217 if ((ip->il_link & IMP_DMASK) == 0) {
218 sc->imp_state = IMPS_GOINGDOWN;
668cc26d 219 timeout(impdown, (caddr_t)sc, 30 * hz);
6c73ade6 220 }
668cc26d
SL
221 impmsg(sc, "going down %s",
222 (u_int)impmessage[ip->il_link&IMP_DMASK]);
72e4f44e 223 goto drop;
6c73ade6
BJ
224
225 /*
226 * A NOP usually seen during the initialization sequence.
227 * Compare the local address with that in the message.
228 * Reset the local address notion if it doesn't match.
229 */
ee787340 230 case IMPTYPE_NOOP:
a0b7c7fb
SL
231 if (sc->imp_state == IMPS_DOWN) {
232 sc->imp_state = IMPS_INIT;
233 sc->imp_dropcnt = IMP_DROPCNT;
234 }
98b6195e 235 if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt > 0)
e431883e 236 goto drop;
98b6195e
SL
237 sin = (struct sockaddr_in *)&sc->imp_if.if_addr;
238 if (sin->sin_addr.s_host != ip->il_host ||
239 sin->sin_addr.s_imp != ip->il_imp) {
240 sc->imp_if.if_host[0] =
241 sin->sin_addr.s_host = ip->il_host;
242 sin->sin_addr.s_imp = ip->il_imp;
243 impmsg(sc, "reset (host %d/imp %d)", (u_int)ip->il_host,
244 ntohs(ip->il_imp));
245 }
a2cd4df7 246 sc->imp_state = IMPS_UP;
ee787340 247 sc->imp_if.if_flags |= IFF_UP;
88f80700 248 if_rtinit(&sc->imp_if, RTF_UP);
e431883e 249 goto drop;
6c73ade6
BJ
250
251 /*
72e4f44e
SL
252 * RFNM or INCOMPLETE message, send next
253 * message on the q. We could pass incomplete's
254 * up to the next level, but this currently isn't
255 * needed.
6c73ade6
BJ
256 */
257 case IMPTYPE_RFNM:
258 case IMPTYPE_INCOMPLETE:
ba45553a
SL
259 if (hp = hostlookup(addr)) {
260 if (hp->h_rfnm == 0)
261 hp->h_flags &= ~HF_INUSE;
262 else if (next = hostdeque(hp))
263 (void) impsnd(&sc->imp_if, next);
264 }
e431883e 265 goto drop;
6c73ade6
BJ
266
267 /*
268 * Host or IMP can't be reached. Flush any packets
269 * awaiting transmission and release the host structure.
6c73ade6
BJ
270 */
271 case IMPTYPE_HOSTDEAD:
ba45553a
SL
272 case IMPTYPE_HOSTUNREACH: {
273 int s = splnet();
6e7edb25
BJ
274 impnotify((int)ip->il_mtype, (struct control_leader *)ip,
275 hostlookup(addr));
ba45553a 276 splx(s);
41e530c7 277 goto rawlinkin;
ba45553a 278 }
6c73ade6
BJ
279
280 /*
281 * Error in data. Clear RFNM status for this host and send
282 * noops to the IMP to clear the interface.
283 */
ba45553a
SL
284 case IMPTYPE_BADDATA: {
285 int s;
286
e33b5b1a 287 impmsg(sc, "data error");
ba45553a
SL
288 s = splnet();
289 if (hp = hostlookup(addr))
6c73ade6 290 hp->h_rfnm = 0;
ba45553a 291 splx(s);
6c73ade6 292 impnoops(sc);
72e4f44e 293 goto drop;
ba45553a 294 }
6c73ade6
BJ
295
296 /*
a0b7c7fb 297 * Interface reset.
6c73ade6
BJ
298 */
299 case IMPTYPE_RESET:
e33b5b1a 300 impmsg(sc, "interface reset");
a0b7c7fb 301 impnoops(sc);
72e4f44e 302 goto drop;
6c73ade6
BJ
303
304 default:
305 sc->imp_if.if_collisions++; /* XXX */
72e4f44e 306 goto drop;
6c73ade6
BJ
307 }
308
309 /*
34c22ab5
BJ
310 * Data for a protocol. Dispatch to the appropriate
311 * protocol routine (running at software interrupt).
312 * If this isn't a raw interface, advance pointer
313 * into mbuf past leader.
6c73ade6
BJ
314 */
315 switch (ip->il_link) {
316
317#ifdef INET
318 case IMPLINK_IP:
319 m->m_len -= sizeof(struct imp_leader);
320 m->m_off += sizeof(struct imp_leader);
9c8692e9 321 schednetisr(NETISR_IP);
6c73ade6
BJ
322 inq = &ipintrq;
323 break;
324#endif
325
326 default:
654fef96 327 rawlinkin:
6c73ade6 328 impproto.sp_protocol = ip->il_link;
ee787340
SL
329 sin = (struct sockaddr_in *)&sc->imp_if.if_addr;
330 impdst.sin_addr = sin->sin_addr;;
faad37c0
SL
331 impsrc.sin_addr.s_net = ip->il_network;
332 impsrc.sin_addr.s_host = ip->il_host;
333 impsrc.sin_addr.s_imp = ip->il_imp;
57aa3090
SL
334 raw_input(m, &impproto, (struct sockaddr *)&impsrc,
335 (struct sockaddr *)&impdst);
6c73ade6
BJ
336 return;
337 }
1e977657
BJ
338 if (IF_QFULL(inq)) {
339 IF_DROP(inq);
340 goto drop;
341 }
6c73ade6
BJ
342 IF_ENQUEUE(inq, m);
343 return;
344
345drop:
346 m_freem(m);
347}
348
a0b7c7fb
SL
349/*
350 * Bring the IMP down after notification.
351 */
352impdown(sc)
353 struct imp_softc *sc;
354{
1e977657 355
a0b7c7fb 356 sc->imp_state = IMPS_DOWN;
e33b5b1a 357 impmsg(sc, "marked down");
ba45553a 358 hostreset(sc->imp_if.if_net);
72e4f44e 359 if_down(&sc->imp_if);
a0b7c7fb
SL
360}
361
6c73ade6 362/*VARARGS*/
e33b5b1a 363impmsg(sc, fmt, a1, a2)
6c73ade6
BJ
364 struct imp_softc *sc;
365 char *fmt;
668cc26d 366 u_int a1;
6c73ade6 367{
1e977657 368
6c73ade6
BJ
369 printf("imp%d: ", sc->imp_if.if_unit);
370 printf(fmt, a1, a2);
371 printf("\n");
372}
373
72e4f44e
SL
374/*
375 * Process an IMP "error" message, passing this
376 * up to the higher level protocol.
377 */
378impnotify(what, cp, hp)
379 int what;
380 struct control_leader *cp;
381 struct host *hp;
382{
383 struct in_addr in;
384
385#ifdef notdef
386 in.s_net = cp->dl_network;
387#else
ba45553a 388 in.s_net = 10; /* XXX */
72e4f44e
SL
389#endif
390 in.s_host = cp->dl_host;
391 in.s_imp = cp->dl_imp;
392 if (cp->dl_link != IMPLINK_IP)
393 raw_ctlinput(what, (caddr_t)&in);
394 else
395 ip_ctlinput(what, (caddr_t)&in);
ba45553a
SL
396 if (hp) {
397 hp->h_flags |= (1 << what);
72e4f44e 398 hostfree(hp);
ba45553a 399 }
72e4f44e
SL
400}
401
6c73ade6
BJ
402/*
403 * ARPAnet 1822 output routine.
404 * Called from higher level protocol routines to set up messages for
405 * transmission to the imp. Sets up the header and calls impsnd to
406 * enqueue the message for this IMP's hardware driver.
407 */
ee787340 408impoutput(ifp, m0, dst)
6c73ade6
BJ
409 register struct ifnet *ifp;
410 struct mbuf *m0;
ee787340 411 struct sockaddr *dst;
6c73ade6
BJ
412{
413 register struct imp_leader *imp;
414 register struct mbuf *m = m0;
39d536e6 415 int dhost, dimp, dlink, len, dnet;
8a2f82db 416 int error = 0;
6c73ade6
BJ
417
418 /*
419 * Don't even try if the IMP is unavailable.
420 */
8a2f82db
SL
421 if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) {
422 error = ENETDOWN;
a0b7c7fb 423 goto drop;
8a2f82db 424 }
6c73ade6 425
ee787340 426 switch (dst->sa_family) {
6c73ade6
BJ
427
428#ifdef INET
ee787340
SL
429 case AF_INET: {
430 struct ip *ip = mtod(m0, struct ip *);
431 struct sockaddr_in *sin = (struct sockaddr_in *)dst;
6c73ade6 432
ee787340
SL
433 dhost = sin->sin_addr.s_host;
434 dimp = sin->sin_addr.s_impno;
6c73ade6 435 dlink = IMPLINK_IP;
1e63a6ab 436 dnet = 0;
668cc26d 437 len = ntohs((u_short)ip->ip_len);
6c73ade6
BJ
438 break;
439 }
440#endif
ee787340 441 case AF_IMPLINK:
6c73ade6
BJ
442 goto leaderexists;
443
444 default:
ee787340
SL
445 printf("imp%d: can't handle af%d\n", ifp->if_unit,
446 dst->sa_family);
8a2f82db 447 error = EAFNOSUPPORT;
a0b7c7fb 448 goto drop;
6c73ade6
BJ
449 }
450
451 /*
452 * Add IMP leader. If there's not enough space in the
453 * first mbuf, allocate another. If that should fail, we
454 * drop this sucker.
455 */
456 if (m->m_off > MMAXOFF ||
457 MMINOFF + sizeof(struct imp_leader) > m->m_off) {
cce93e4b 458 m = m_get(M_DONTWAIT, MT_HEADER);
8a2f82db
SL
459 if (m == 0) {
460 error = ENOBUFS;
a0b7c7fb 461 goto drop;
8a2f82db 462 }
6c73ade6 463 m->m_next = m0;
6c73ade6
BJ
464 m->m_len = sizeof(struct imp_leader);
465 } else {
466 m->m_off -= sizeof(struct imp_leader);
467 m->m_len += sizeof(struct imp_leader);
468 }
469 imp = mtod(m, struct imp_leader *);
470 imp->il_format = IMP_NFF;
41e530c7 471 imp->il_mtype = IMPTYPE_DATA;
1e63a6ab 472 imp->il_network = dnet;
6c73ade6 473 imp->il_host = dhost;
1e63a6ab 474 imp->il_imp = htons((u_short)dimp);
668cc26d
SL
475 imp->il_length =
476 htons((u_short)(len + sizeof(struct imp_leader)) << 3);
6c73ade6 477 imp->il_link = dlink;
41e530c7 478 imp->il_flags = imp->il_htype = imp->il_subtype = 0;
6c73ade6
BJ
479
480leaderexists:
6c73ade6 481 return (impsnd(ifp, m));
a0b7c7fb
SL
482drop:
483 m_freem(m0);
8a2f82db 484 return (error);
6c73ade6
BJ
485}
486
487/*
488 * Put a message on an interface's output queue.
489 * Perform RFNM counting: no more than 8 message may be
490 * in flight to any one host.
491 */
492impsnd(ifp, m)
493 struct ifnet *ifp;
494 struct mbuf *m;
495{
496 register struct imp_leader *ip;
497 register struct host *hp;
498 struct impcb *icp;
ba45553a 499 int s, error;
6c73ade6
BJ
500
501 ip = mtod(m, struct imp_leader *);
502
503 /*
504 * Do RFNM counting for data messages
505 * (no more than 8 outstanding to any host)
506 */
ba45553a 507 s = splimp();
6c73ade6
BJ
508 if (ip->il_mtype == IMPTYPE_DATA) {
509 struct in_addr addr;
510
41e530c7 511#ifdef notdef
a2cd4df7 512 addr.s_net = ip->il_network;
41e530c7 513#else
ba45553a 514 addr.s_net = ifp->if_net; /* XXX */
41e530c7 515#endif
6c73ade6
BJ
516 addr.s_host = ip->il_host;
517 addr.s_imp = ip->il_imp;
a2cd4df7
BJ
518 if ((hp = hostlookup(addr)) == 0)
519 hp = hostenter(addr);
ba45553a 520 if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) {
67387c9c 521 error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH;
ba45553a
SL
522 hp->h_timer = HOSTTIMER;
523 hp->h_flags &= ~HF_INUSE;
524 goto bad;
ba45553a 525 }
6c73ade6
BJ
526
527 /*
a0b7c7fb 528 * If IMP would block, queue until RFNM
6c73ade6
BJ
529 */
530 if (hp) {
6c73ade6
BJ
531 if (hp->h_rfnm < 8) {
532 hp->h_rfnm++;
533 goto enque;
534 }
fcd78660
BJ
535 if (hp->h_qcnt < 8) { /* high water mark */
536 HOST_ENQUE(hp, m);
537 goto start;
538 }
6c73ade6 539 }
ba45553a
SL
540 error = ENOBUFS;
541 goto bad;
6c73ade6
BJ
542 }
543enque:
1e977657
BJ
544 if (IF_QFULL(&ifp->if_snd)) {
545 IF_DROP(&ifp->if_snd);
ba45553a
SL
546 error = ENOBUFS;
547bad:
1e977657 548 m_freem(m);
ba45553a
SL
549 splx(s);
550 return (error);
1e977657 551 }
6c73ade6 552 IF_ENQUEUE(&ifp->if_snd, m);
6c73ade6
BJ
553start:
554 icp = &imp_softc[ifp->if_unit].imp_cb;
555 if (icp->ic_oactive == 0)
556 (*icp->ic_start)(ifp->if_unit);
70e3101c 557 splx(s);
8a2f82db 558 return (0);
6c73ade6
BJ
559}
560
561/*
562 * Put three 1822 NOOPs at the head of the output queue.
563 * Part of host-IMP initialization procedure.
564 * (Should return success/failure, but noone knows
565 * what to do with this, so why bother?)
0dc78444
SL
566 * This routine is always called at splimp, so we don't
567 * protect the call to IF_PREPEND.
6c73ade6
BJ
568 */
569impnoops(sc)
570 register struct imp_softc *sc;
571{
572 register i;
573 register struct mbuf *m;
a2cd4df7 574 register struct control_leader *cp;
6c73ade6 575
6c73ade6 576 sc->imp_dropcnt = IMP_DROPCNT;
a2cd4df7 577 for (i = 0; i < IMP_DROPCNT + 1; i++ ) {
cce93e4b 578 if ((m = m_getclr(M_DONTWAIT, MT_HEADER)) == 0)
6c73ade6 579 return;
a2cd4df7
BJ
580 m->m_len = sizeof(struct control_leader);
581 cp = mtod(m, struct control_leader *);
582 cp->dl_format = IMP_NFF;
583 cp->dl_link = i;
584 cp->dl_mtype = IMPTYPE_NOOP;
6c73ade6 585 IF_PREPEND(&sc->imp_if.if_snd, m);
6c73ade6
BJ
586 }
587 if (sc->imp_cb.ic_oactive == 0)
588 (*sc->imp_cb.ic_start)(sc->imp_if.if_unit);
589}
7dfb87a5
SL
590
591#ifdef IMPLEADERS
592printleader(routine, ip)
593 char *routine;
594 register struct imp_leader *ip;
595{
596 printf("%s: ", routine);
597 printbyte((char *)ip, 12);
598 printf("<fmt=%x,net=%x,flags=%x,mtype=", ip->il_format, ip->il_network,
599 ip->il_flags);
600 if (ip->il_mtype <= IMPTYPE_READY)
601 printf("%s,", impleaders[ip->il_mtype]);
602 else
603 printf("%x,", ip->il_mtype);
604 printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host,
605 ntohs(ip->il_imp));
606 if (ip->il_link == IMPLINK_IP)
607 printf("ip,");
608 else
609 printf("%x,", ip->il_link);
610 printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3);
611}
612
613printbyte(cp, n)
614 register char *cp;
615 int n;
616{
617 register i, j, c;
618
619 for (i=0; i<n; i++) {
620 c = *cp++;
621 for (j=0; j<2; j++)
622 putchar("0123456789abcdef"[(c>>((1-j)*4))&0xf]);
623 putchar(' ');
624 }
625 putchar('\n');
626}
627#endif
41e530c7 628#endif