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