Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/net/if_fwsubr.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 2004 Doug Rabson
5
* Copyright (c) 1982, 1989, 1993
6
* The Regents of the University of California. All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
* 3. Neither the name of the University nor the names of its contributors
17
* may be used to endorse or promote products derived from this software
18
* without specific prior written permission.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
* SUCH DAMAGE.
31
*/
32
33
#include "opt_inet.h"
34
#include "opt_inet6.h"
35
36
#include <sys/param.h>
37
#include <sys/systm.h>
38
#include <sys/kernel.h>
39
#include <sys/malloc.h>
40
#include <sys/mbuf.h>
41
#include <sys/module.h>
42
#include <sys/socket.h>
43
#include <sys/sockio.h>
44
45
#include <net/if.h>
46
#include <net/if_var.h>
47
#include <net/if_private.h>
48
#include <net/netisr.h>
49
#include <net/route.h>
50
#include <net/if_llc.h>
51
#include <net/if_dl.h>
52
#include <net/if_types.h>
53
#include <net/bpf.h>
54
#include <net/firewire.h>
55
#include <net/if_llatbl.h>
56
57
#if defined(INET) || defined(INET6)
58
#include <netinet/in.h>
59
#include <netinet/in_var.h>
60
#include <netinet/if_ether.h>
61
#endif
62
#ifdef INET6
63
#include <netinet6/nd6.h>
64
#endif
65
66
#include <security/mac/mac_framework.h>
67
68
static MALLOC_DEFINE(M_FWCOM, "fw_com", "firewire interface internals");
69
70
static const struct fw_hwaddr firewire_broadcastaddr = {
71
0xffffffff,
72
0xffffffff,
73
0xff,
74
0xff,
75
0xffff,
76
0xffffffff
77
};
78
79
static int
80
firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
81
struct route *ro)
82
{
83
struct fw_com *fc = IFP2FWC(ifp);
84
int error, type;
85
struct m_tag *mtag;
86
union fw_encap *enc;
87
struct fw_hwaddr *destfw;
88
uint8_t speed;
89
uint16_t psize, fsize, dsize;
90
struct mbuf *mtail;
91
int unicast, dgl, foff;
92
static int next_dgl;
93
#if defined(INET) || defined(INET6)
94
int is_gw = 0;
95
#endif
96
int af = RO_GET_FAMILY(ro, dst);
97
98
#ifdef MAC
99
error = mac_ifnet_check_transmit(ifp, m);
100
if (error)
101
goto bad;
102
#endif
103
104
if (!((ifp->if_flags & IFF_UP) &&
105
(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
106
error = ENETDOWN;
107
goto bad;
108
}
109
110
#if defined(INET) || defined(INET6)
111
if (ro != NULL)
112
is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
113
#endif
114
/*
115
* For unicast, we make a tag to store the lladdr of the
116
* destination. This might not be the first time we have seen
117
* the packet (for instance, the arp code might be trying to
118
* re-send it after receiving an arp reply) so we only
119
* allocate a tag if there isn't one there already. For
120
* multicast, we will eventually use a different tag to store
121
* the channel number.
122
*/
123
unicast = !(m->m_flags & (M_BCAST | M_MCAST));
124
if (unicast) {
125
mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, NULL);
126
if (!mtag) {
127
mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR,
128
sizeof (struct fw_hwaddr), M_NOWAIT);
129
if (!mtag) {
130
error = ENOMEM;
131
goto bad;
132
}
133
m_tag_prepend(m, mtag);
134
}
135
destfw = (struct fw_hwaddr *)(mtag + 1);
136
} else {
137
destfw = NULL;
138
}
139
140
switch (af) {
141
#ifdef INET
142
case AF_INET:
143
type = ETHERTYPE_IP;
144
break;
145
case AF_ARP:
146
type = ETHERTYPE_ARP;
147
break;
148
#endif
149
#ifdef INET6
150
case AF_INET6:
151
type = ETHERTYPE_IPV6;
152
break;
153
#endif
154
default:
155
if_printf(ifp, "can't handle af%d\n", af);
156
error = EAFNOSUPPORT;
157
goto bad;
158
}
159
160
switch (dst->sa_family) {
161
#ifdef INET
162
case AF_INET:
163
/*
164
* Only bother with arp for unicast. Allocation of
165
* channels etc. for firewire is quite different and
166
* doesn't fit into the arp model.
167
*/
168
if (unicast) {
169
error = arpresolve(ifp, is_gw, m, dst,
170
(u_char *) destfw, NULL, NULL);
171
if (error)
172
return (error == EWOULDBLOCK ? 0 : error);
173
}
174
break;
175
176
case AF_ARP:
177
{
178
struct arphdr *ah;
179
ah = mtod(m, struct arphdr *);
180
ah->ar_hrd = htons(ARPHRD_IEEE1394);
181
if (unicast)
182
*destfw = *(struct fw_hwaddr *) ar_tha(ah);
183
184
/*
185
* The standard arp code leaves a hole for the target
186
* hardware address which we need to close up.
187
*/
188
bcopy(ar_tpa(ah), ar_tha(ah), ah->ar_pln);
189
m_adj(m, -ah->ar_hln);
190
break;
191
}
192
#endif
193
194
#ifdef INET6
195
case AF_INET6:
196
if (unicast) {
197
error = nd6_resolve(fc->fc_ifp, LLE_SF(af, is_gw), m,
198
dst, (u_char *) destfw, NULL, NULL);
199
if (error)
200
return (error == EWOULDBLOCK ? 0 : error);
201
}
202
break;
203
#endif
204
205
default:
206
if_printf(ifp, "can't handle af%d\n", dst->sa_family);
207
error = EAFNOSUPPORT;
208
goto bad;
209
}
210
211
/*
212
* Let BPF tap off a copy before we encapsulate.
213
*/
214
if (bpf_peers_present(ifp->if_bpf)) {
215
struct fw_bpfhdr h;
216
if (unicast)
217
bcopy(destfw, h.firewire_dhost, 8);
218
else
219
bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8);
220
bcopy(&fc->fc_hwaddr, h.firewire_shost, 8);
221
h.firewire_type = htons(type);
222
bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m);
223
}
224
225
/*
226
* Punt on MCAP for now and send all multicast packets on the
227
* broadcast channel.
228
*/
229
if (m->m_flags & M_MCAST)
230
m->m_flags |= M_BCAST;
231
232
/*
233
* Figure out what speed to use and what the largest supported
234
* packet size is. For unicast, this is the minimum of what we
235
* can speak and what they can hear. For broadcast, lets be
236
* conservative and use S100. We could possibly improve that
237
* by examining the bus manager's speed map or similar. We
238
* also reduce the packet size for broadcast to account for
239
* the GASP header.
240
*/
241
if (unicast) {
242
speed = min(fc->fc_speed, destfw->sspd);
243
psize = min(512 << speed, 2 << destfw->sender_max_rec);
244
} else {
245
speed = 0;
246
psize = 512 - 2*sizeof(uint32_t);
247
}
248
249
/*
250
* Next, we encapsulate, possibly fragmenting the original
251
* datagram if it won't fit into a single packet.
252
*/
253
if (m->m_pkthdr.len <= psize - sizeof(uint32_t)) {
254
/*
255
* No fragmentation is necessary.
256
*/
257
M_PREPEND(m, sizeof(uint32_t), M_NOWAIT);
258
if (!m) {
259
error = ENOBUFS;
260
goto bad;
261
}
262
enc = mtod(m, union fw_encap *);
263
enc->unfrag.ether_type = type;
264
enc->unfrag.lf = FW_ENCAP_UNFRAG;
265
enc->unfrag.reserved = 0;
266
267
/*
268
* Byte swap the encapsulation header manually.
269
*/
270
enc->ul[0] = htonl(enc->ul[0]);
271
272
error = (ifp->if_transmit)(ifp, m);
273
return (error);
274
} else {
275
/*
276
* Fragment the datagram, making sure to leave enough
277
* space for the encapsulation header in each packet.
278
*/
279
fsize = psize - 2*sizeof(uint32_t);
280
dgl = next_dgl++;
281
dsize = m->m_pkthdr.len;
282
foff = 0;
283
while (m) {
284
if (m->m_pkthdr.len > fsize) {
285
/*
286
* Split off the tail segment from the
287
* datagram, copying our tags over.
288
*/
289
mtail = m_split(m, fsize, M_NOWAIT);
290
m_tag_copy_chain(mtail, m, M_NOWAIT);
291
} else {
292
mtail = NULL;
293
}
294
295
/*
296
* Add our encapsulation header to this
297
* fragment and hand it off to the link.
298
*/
299
M_PREPEND(m, 2*sizeof(uint32_t), M_NOWAIT);
300
if (!m) {
301
error = ENOBUFS;
302
goto bad;
303
}
304
enc = mtod(m, union fw_encap *);
305
if (foff == 0) {
306
enc->firstfrag.lf = FW_ENCAP_FIRST;
307
enc->firstfrag.reserved1 = 0;
308
enc->firstfrag.reserved2 = 0;
309
enc->firstfrag.datagram_size = dsize - 1;
310
enc->firstfrag.ether_type = type;
311
enc->firstfrag.dgl = dgl;
312
} else {
313
if (mtail)
314
enc->nextfrag.lf = FW_ENCAP_NEXT;
315
else
316
enc->nextfrag.lf = FW_ENCAP_LAST;
317
enc->nextfrag.reserved1 = 0;
318
enc->nextfrag.reserved2 = 0;
319
enc->nextfrag.reserved3 = 0;
320
enc->nextfrag.datagram_size = dsize - 1;
321
enc->nextfrag.fragment_offset = foff;
322
enc->nextfrag.dgl = dgl;
323
}
324
foff += m->m_pkthdr.len - 2*sizeof(uint32_t);
325
326
/*
327
* Byte swap the encapsulation header manually.
328
*/
329
enc->ul[0] = htonl(enc->ul[0]);
330
enc->ul[1] = htonl(enc->ul[1]);
331
332
error = (ifp->if_transmit)(ifp, m);
333
if (error) {
334
if (mtail)
335
m_freem(mtail);
336
return (ENOBUFS);
337
}
338
339
m = mtail;
340
}
341
342
return (0);
343
}
344
345
bad:
346
if (m)
347
m_freem(m);
348
return (error);
349
}
350
351
static struct mbuf *
352
firewire_input_fragment(struct fw_com *fc, struct mbuf *m, int src)
353
{
354
union fw_encap *enc;
355
struct fw_reass *r;
356
struct mbuf *mf, *mprev;
357
int dsize;
358
int fstart, fend, start, end, islast;
359
uint32_t id;
360
361
/*
362
* Find an existing reassembly buffer or create a new one.
363
*/
364
enc = mtod(m, union fw_encap *);
365
id = enc->firstfrag.dgl | (src << 16);
366
STAILQ_FOREACH(r, &fc->fc_frags, fr_link)
367
if (r->fr_id == id)
368
break;
369
if (!r) {
370
r = malloc(sizeof(struct fw_reass), M_TEMP, M_NOWAIT);
371
if (!r) {
372
m_freem(m);
373
return 0;
374
}
375
r->fr_id = id;
376
r->fr_frags = 0;
377
STAILQ_INSERT_HEAD(&fc->fc_frags, r, fr_link);
378
}
379
380
/*
381
* If this fragment overlaps any other fragment, we must discard
382
* the partial reassembly and start again.
383
*/
384
if (enc->firstfrag.lf == FW_ENCAP_FIRST)
385
fstart = 0;
386
else
387
fstart = enc->nextfrag.fragment_offset;
388
fend = fstart + m->m_pkthdr.len - 2*sizeof(uint32_t);
389
dsize = enc->nextfrag.datagram_size;
390
islast = (enc->nextfrag.lf == FW_ENCAP_LAST);
391
392
for (mf = r->fr_frags; mf; mf = mf->m_nextpkt) {
393
enc = mtod(mf, union fw_encap *);
394
if (enc->nextfrag.datagram_size != dsize) {
395
/*
396
* This fragment must be from a different
397
* packet.
398
*/
399
goto bad;
400
}
401
if (enc->firstfrag.lf == FW_ENCAP_FIRST)
402
start = 0;
403
else
404
start = enc->nextfrag.fragment_offset;
405
end = start + mf->m_pkthdr.len - 2*sizeof(uint32_t);
406
if ((fstart < end && fend > start) ||
407
(islast && enc->nextfrag.lf == FW_ENCAP_LAST)) {
408
/*
409
* Overlap - discard reassembly buffer and start
410
* again with this fragment.
411
*/
412
goto bad;
413
}
414
}
415
416
/*
417
* Find where to put this fragment in the list.
418
*/
419
for (mf = r->fr_frags, mprev = NULL; mf;
420
mprev = mf, mf = mf->m_nextpkt) {
421
enc = mtod(mf, union fw_encap *);
422
if (enc->firstfrag.lf == FW_ENCAP_FIRST)
423
start = 0;
424
else
425
start = enc->nextfrag.fragment_offset;
426
if (start >= fend)
427
break;
428
}
429
430
/*
431
* If this is a last fragment and we are not adding at the end
432
* of the list, discard the buffer.
433
*/
434
if (islast && mprev && mprev->m_nextpkt)
435
goto bad;
436
437
if (mprev) {
438
m->m_nextpkt = mprev->m_nextpkt;
439
mprev->m_nextpkt = m;
440
441
/*
442
* Coalesce forwards and see if we can make a whole
443
* datagram.
444
*/
445
enc = mtod(mprev, union fw_encap *);
446
if (enc->firstfrag.lf == FW_ENCAP_FIRST)
447
start = 0;
448
else
449
start = enc->nextfrag.fragment_offset;
450
end = start + mprev->m_pkthdr.len - 2*sizeof(uint32_t);
451
while (end == fstart) {
452
/*
453
* Strip off the encap header from m and
454
* append it to mprev, freeing m.
455
*/
456
m_adj(m, 2*sizeof(uint32_t));
457
mprev->m_nextpkt = m->m_nextpkt;
458
mprev->m_pkthdr.len += m->m_pkthdr.len;
459
m_cat(mprev, m);
460
461
if (mprev->m_pkthdr.len == dsize + 1 + 2*sizeof(uint32_t)) {
462
/*
463
* We have assembled a complete packet
464
* we must be finished. Make sure we have
465
* merged the whole chain.
466
*/
467
STAILQ_REMOVE(&fc->fc_frags, r, fw_reass, fr_link);
468
free(r, M_TEMP);
469
m = mprev->m_nextpkt;
470
while (m) {
471
mf = m->m_nextpkt;
472
m_freem(m);
473
m = mf;
474
}
475
mprev->m_nextpkt = NULL;
476
477
return (mprev);
478
}
479
480
/*
481
* See if we can continue merging forwards.
482
*/
483
end = fend;
484
m = mprev->m_nextpkt;
485
if (m) {
486
enc = mtod(m, union fw_encap *);
487
if (enc->firstfrag.lf == FW_ENCAP_FIRST)
488
fstart = 0;
489
else
490
fstart = enc->nextfrag.fragment_offset;
491
fend = fstart + m->m_pkthdr.len
492
- 2*sizeof(uint32_t);
493
} else {
494
break;
495
}
496
}
497
} else {
498
m->m_nextpkt = 0;
499
r->fr_frags = m;
500
}
501
502
return (0);
503
504
bad:
505
while (r->fr_frags) {
506
mf = r->fr_frags;
507
r->fr_frags = mf->m_nextpkt;
508
m_freem(mf);
509
}
510
m->m_nextpkt = 0;
511
r->fr_frags = m;
512
513
return (0);
514
}
515
516
void
517
firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src)
518
{
519
struct fw_com *fc = IFP2FWC(ifp);
520
union fw_encap *enc;
521
int type, isr;
522
523
/*
524
* The caller has already stripped off the packet header
525
* (stream or wreqb) and marked the mbuf's M_BCAST flag
526
* appropriately. We de-encapsulate the IP packet and pass it
527
* up the line after handling link-level fragmentation.
528
*/
529
if (m->m_pkthdr.len < sizeof(uint32_t)) {
530
if_printf(ifp, "discarding frame without "
531
"encapsulation header (len %u pkt len %u)\n",
532
m->m_len, m->m_pkthdr.len);
533
}
534
535
m = m_pullup(m, sizeof(uint32_t));
536
if (m == NULL)
537
return;
538
enc = mtod(m, union fw_encap *);
539
540
/*
541
* Byte swap the encapsulation header manually.
542
*/
543
enc->ul[0] = ntohl(enc->ul[0]);
544
545
if (enc->unfrag.lf != 0) {
546
m = m_pullup(m, 2*sizeof(uint32_t));
547
if (!m)
548
return;
549
enc = mtod(m, union fw_encap *);
550
enc->ul[1] = ntohl(enc->ul[1]);
551
m = firewire_input_fragment(fc, m, src);
552
if (!m)
553
return;
554
enc = mtod(m, union fw_encap *);
555
type = enc->firstfrag.ether_type;
556
m_adj(m, 2*sizeof(uint32_t));
557
} else {
558
type = enc->unfrag.ether_type;
559
m_adj(m, sizeof(uint32_t));
560
}
561
562
if (m->m_pkthdr.rcvif == NULL) {
563
if_printf(ifp, "discard frame w/o interface pointer\n");
564
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
565
m_freem(m);
566
return;
567
}
568
#ifdef DIAGNOSTIC
569
if (m->m_pkthdr.rcvif != ifp) {
570
if_printf(ifp, "Warning, frame marked as received on %s\n",
571
m->m_pkthdr.rcvif->if_xname);
572
}
573
#endif
574
575
#ifdef MAC
576
/*
577
* Tag the mbuf with an appropriate MAC label before any other
578
* consumers can get to it.
579
*/
580
mac_ifnet_create_mbuf(ifp, m);
581
#endif
582
583
/*
584
* Give bpf a chance at the packet. The link-level driver
585
* should have left us a tag with the EUID of the sender.
586
*/
587
if (bpf_peers_present(ifp->if_bpf)) {
588
struct fw_bpfhdr h;
589
struct m_tag *mtag;
590
591
mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 0);
592
if (mtag)
593
bcopy(mtag + 1, h.firewire_shost, 8);
594
else
595
bcopy(&firewire_broadcastaddr, h.firewire_dhost, 8);
596
bcopy(&fc->fc_hwaddr, h.firewire_dhost, 8);
597
h.firewire_type = htons(type);
598
bpf_mtap2(ifp->if_bpf, &h, sizeof(h), m);
599
}
600
601
if (ifp->if_flags & IFF_MONITOR) {
602
/*
603
* Interface marked for monitoring; discard packet.
604
*/
605
m_freem(m);
606
return;
607
}
608
609
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
610
611
/* Discard packet if interface is not up */
612
if ((ifp->if_flags & IFF_UP) == 0) {
613
m_freem(m);
614
return;
615
}
616
617
if (m->m_flags & (M_BCAST|M_MCAST))
618
if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1);
619
620
switch (type) {
621
#ifdef INET
622
case ETHERTYPE_IP:
623
isr = NETISR_IP;
624
break;
625
626
case ETHERTYPE_ARP:
627
{
628
struct arphdr *ah;
629
ah = mtod(m, struct arphdr *);
630
631
/*
632
* Adjust the arp packet to insert an empty tha slot.
633
*/
634
m->m_len += ah->ar_hln;
635
m->m_pkthdr.len += ah->ar_hln;
636
bcopy(ar_tha(ah), ar_tpa(ah), ah->ar_pln);
637
isr = NETISR_ARP;
638
break;
639
}
640
#endif
641
642
#ifdef INET6
643
case ETHERTYPE_IPV6:
644
isr = NETISR_IPV6;
645
break;
646
#endif
647
648
default:
649
m_freem(m);
650
return;
651
}
652
653
M_SETFIB(m, ifp->if_fib);
654
CURVNET_SET_QUIET(ifp->if_vnet);
655
netisr_dispatch(isr, m);
656
CURVNET_RESTORE();
657
}
658
659
int
660
firewire_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
661
{
662
struct ifaddr *ifa = (struct ifaddr *) data;
663
struct ifreq *ifr = (struct ifreq *) data;
664
int error = 0;
665
666
switch (command) {
667
case SIOCSIFADDR:
668
ifp->if_flags |= IFF_UP;
669
670
switch (ifa->ifa_addr->sa_family) {
671
#ifdef INET
672
case AF_INET:
673
ifp->if_init(ifp->if_softc); /* before arpwhohas */
674
arp_ifinit(ifp, ifa);
675
break;
676
#endif
677
default:
678
ifp->if_init(ifp->if_softc);
679
break;
680
}
681
break;
682
683
case SIOCGIFADDR:
684
bcopy(&IFP2FWC(ifp)->fc_hwaddr, &ifr->ifr_addr.sa_data[0],
685
sizeof(struct fw_hwaddr));
686
break;
687
688
case SIOCSIFMTU:
689
/*
690
* Set the interface MTU.
691
*/
692
if (ifr->ifr_mtu > 1500) {
693
error = EINVAL;
694
} else {
695
ifp->if_mtu = ifr->ifr_mtu;
696
}
697
break;
698
default:
699
error = EINVAL; /* XXX netbsd has ENOTTY??? */
700
break;
701
}
702
return (error);
703
}
704
705
static int
706
firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa,
707
struct sockaddr *sa)
708
{
709
#ifdef INET
710
struct sockaddr_in *sin;
711
#endif
712
#ifdef INET6
713
struct sockaddr_in6 *sin6;
714
#endif
715
716
switch(sa->sa_family) {
717
case AF_LINK:
718
/*
719
* No mapping needed.
720
*/
721
*llsa = NULL;
722
return 0;
723
724
#ifdef INET
725
case AF_INET:
726
sin = (struct sockaddr_in *)sa;
727
if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
728
return EADDRNOTAVAIL;
729
*llsa = NULL;
730
return 0;
731
#endif
732
#ifdef INET6
733
case AF_INET6:
734
sin6 = (struct sockaddr_in6 *)sa;
735
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
736
/*
737
* An IP6 address of 0 means listen to all
738
* of the Ethernet multicast address used for IP6.
739
* (This is used for multicast routers.)
740
*/
741
ifp->if_flags |= IFF_ALLMULTI;
742
*llsa = NULL;
743
return 0;
744
}
745
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
746
return EADDRNOTAVAIL;
747
*llsa = NULL;
748
return 0;
749
#endif
750
751
default:
752
/*
753
* Well, the text isn't quite right, but it's the name
754
* that counts...
755
*/
756
return EAFNOSUPPORT;
757
}
758
}
759
760
void
761
firewire_ifattach(struct ifnet *ifp, struct fw_hwaddr *llc)
762
{
763
struct fw_com *fc = IFP2FWC(ifp);
764
struct ifaddr *ifa;
765
struct sockaddr_dl *sdl;
766
static const char* speeds[] = {
767
"S100", "S200", "S400", "S800",
768
"S1600", "S3200"
769
};
770
771
fc->fc_speed = llc->sspd;
772
STAILQ_INIT(&fc->fc_frags);
773
774
ifp->if_addrlen = sizeof(struct fw_hwaddr);
775
ifp->if_hdrlen = 0;
776
if_attach(ifp);
777
ifp->if_mtu = 1500; /* XXX */
778
ifp->if_output = firewire_output;
779
ifp->if_resolvemulti = firewire_resolvemulti;
780
ifp->if_broadcastaddr = (const u_char *) &firewire_broadcastaddr;
781
782
ifa = ifp->if_addr;
783
KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
784
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
785
sdl->sdl_type = IFT_IEEE1394;
786
sdl->sdl_alen = ifp->if_addrlen;
787
bcopy(llc, LLADDR(sdl), ifp->if_addrlen);
788
789
bpfattach(ifp, DLT_APPLE_IP_OVER_IEEE1394,
790
sizeof(struct fw_hwaddr));
791
792
if_printf(ifp, "Firewire address: %8D @ 0x%04x%08x, %s, maxrec %d\n",
793
(uint8_t *) &llc->sender_unique_ID_hi, ":",
794
ntohs(llc->sender_unicast_FIFO_hi),
795
ntohl(llc->sender_unicast_FIFO_lo),
796
speeds[llc->sspd],
797
(2 << llc->sender_max_rec));
798
}
799
800
void
801
firewire_ifdetach(struct ifnet *ifp)
802
{
803
bpfdetach(ifp);
804
if_detach(ifp);
805
NET_EPOCH_DRAIN_CALLBACKS();
806
}
807
808
void
809
firewire_busreset(struct ifnet *ifp)
810
{
811
struct fw_com *fc = IFP2FWC(ifp);
812
struct fw_reass *r;
813
struct mbuf *m;
814
815
/*
816
* Discard any partial datagrams since the host ids may have changed.
817
*/
818
while ((r = STAILQ_FIRST(&fc->fc_frags))) {
819
STAILQ_REMOVE_HEAD(&fc->fc_frags, fr_link);
820
while (r->fr_frags) {
821
m = r->fr_frags;
822
r->fr_frags = m->m_nextpkt;
823
m_freem(m);
824
}
825
free(r, M_TEMP);
826
}
827
}
828
829
static void *
830
firewire_alloc(u_char type, struct ifnet *ifp)
831
{
832
struct fw_com *fc;
833
834
fc = malloc(sizeof(struct fw_com), M_FWCOM, M_WAITOK | M_ZERO);
835
fc->fc_ifp = ifp;
836
837
return (fc);
838
}
839
840
static void
841
firewire_free(void *com, u_char type)
842
{
843
844
free(com, M_FWCOM);
845
}
846
847
static int
848
firewire_modevent(module_t mod, int type, void *data)
849
{
850
851
switch (type) {
852
case MOD_LOAD:
853
if_register_com_alloc(IFT_IEEE1394,
854
firewire_alloc, firewire_free);
855
break;
856
case MOD_UNLOAD:
857
if_deregister_com_alloc(IFT_IEEE1394);
858
break;
859
default:
860
return (EOPNOTSUPP);
861
}
862
863
return (0);
864
}
865
866
static moduledata_t firewire_mod = {
867
"if_firewire",
868
firewire_modevent,
869
0
870
};
871
872
DECLARE_MODULE(if_firewire, firewire_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
873
MODULE_VERSION(if_firewire, 1);
874
875