]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - VBLADE/vblade-master/freebsd.c
2 * Copyright (c) 2005, Stacey Son <sson (at) verio (dot) net>
6 // freebsd.c: low level access routines for FreeBSD
9 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <net/ethernet.h>
20 #include <net/if_arp.h>
21 #include <net/if_dl.h>
22 #include <net/route.h>
24 #include <sys/ioctl.h>
25 #include <sys/types.h>
29 #include <sys/select.h>
30 #include <sys/sysctl.h>
38 #define BPF_DEV "/dev/bpf0"
40 /* Packet buffer for getpkt() */
41 static uchar
*pktbuf
= NULL
;
42 static int pktbufsz
= 0;
45 dial(char *eth
, int bufcnt
)
49 struct bpf_version bv
;
51 unsigned bufsize
, linktype
;
52 char device
[sizeof BPF_DEV
];
55 struct bpf_program
*bpf_program
= create_bpf_program(shelf
, slot
);
57 strncpy(device
, BPF_DEV
, sizeof BPF_DEV
);
59 /* find a bpf device we can use, check /dev/bpf[0-9] */
60 for (m
= '0'; m
<= '9'; m
++) {
61 device
[sizeof(BPF_DEV
)-2] = m
;
63 if ((fd
= open(device
, O_RDWR
)) > 0)
72 if (ioctl(fd
, BIOCVERSION
, &bv
) < 0) {
73 perror("BIOCVERSION");
77 if (bv
.bv_major
!= BPF_MAJOR_VERSION
||
78 bv
.bv_minor
< BPF_MINOR_VERSION
) {
80 "kernel bpf filter out of date\n");
85 * Try finding a good size for the buffer; 65536 may be too
86 * big, so keep cutting it in half until we find a size
87 * that works, or run out of sizes to try.
90 for (v
= 65536; v
!= 0; v
>>= 1) {
91 (void) ioctl(fd
, BIOCSBLEN
, (caddr_t
)&v
);
93 (void)strncpy(ifr
.ifr_name
, eth
,
94 sizeof(ifr
.ifr_name
));
95 if (ioctl(fd
, BIOCSETIF
, (caddr_t
)&ifr
) >= 0)
96 break; /* that size worked; we're done */
98 if (errno
!= ENOBUFS
) {
99 fprintf(stderr
, "BIOCSETIF: %s: %s\n",
100 eth
, strerror(errno
));
106 "BIOCSBLEN: %s: No buffer size worked\n", eth
);
110 /* Allocate memory for the packet buffer */
112 if ((pktbuf
= malloc(pktbufsz
)) == NULL
) {
117 /* Don't wait for buffer to be full or timeout */
119 if (ioctl(fd
, BIOCIMMEDIATE
, &v
) < 0) {
120 perror("BIOCIMMEDIATE");
124 /* Only read incoming packets */
126 if (ioctl(fd
, BIOCSSEESENT
, &v
) < 0) {
127 perror("BIOCSSEESENT");
131 /* Don't complete ethernet hdr */
133 if (ioctl(fd
, BIOCSHDRCMPLT
, &v
) < 0) {
134 perror("BIOCSHDRCMPLT");
138 /* Get the data link layer type. */
139 if (ioctl(fd
, BIOCGDLT
, (caddr_t
)&v
) < 0) {
145 /* Get the filter buf size */
146 if (ioctl(fd
, BIOCGBLEN
, (caddr_t
)&v
) < 0) {
152 if (ioctl(fd
, BIOCSETF
, (caddr_t
)bpf_program
) < 0) {
157 free_bpf_program(bpf_program
);
161 free_bpf_program(bpf_program
);
167 getea(int s
, char *eth
, uchar
*ea
)
171 char *buf
, *next
, *end
;
172 struct if_msghdr
*ifm
;
173 struct sockaddr_dl
*sdl
;
176 mib
[0] = CTL_NET
; mib
[1] = AF_ROUTE
;
177 mib
[2] = 0; mib
[3] = AF_LINK
;
178 mib
[4] = NET_RT_IFLIST
; mib
[5] = 0;
180 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0) {
184 if (!(buf
= (char *) malloc(len
))) {
188 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
194 for (next
= buf
; next
< end
; next
+= ifm
->ifm_msglen
) {
195 ifm
= (struct if_msghdr
*)next
;
196 if (ifm
->ifm_type
== RTM_IFINFO
) {
197 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
198 if (strncmp(&sdl
->sdl_data
[0], eth
,
199 sdl
->sdl_nlen
) == 0) {
200 memcpy(ea
, LLADDR(sdl
), ETHER_ADDR_LEN
);
215 getsec(int fd
, uchar
*place
, vlong lba
, int nsec
)
217 return pread(fd
, place
, nsec
* 512, lba
* 512);
221 putsec(int fd
, uchar
*place
, vlong lba
, int nsec
)
223 return pwrite(fd
, place
, nsec
* 512, lba
* 512);
228 static uchar
*pktbp
= NULL
;
231 getpkt(int fd
, uchar
*buf
, int sz
)
233 register struct bpf_hdr
*bh
;
234 register int pktlen
, retlen
;
237 if ((pktn
= read(fd
, pktbuf
, pktbufsz
)) < 0) {
244 bh
= (struct bpf_hdr
*) pktbp
;
245 retlen
= (int) bh
->bh_caplen
;
246 /* This memcpy() is currently needed */
247 memcpy(buf
, (void *)(pktbp
+ bh
->bh_hdrlen
),
248 retlen
> sz
? sz
: retlen
);
249 pktlen
= bh
->bh_hdrlen
+ bh
->bh_caplen
;
251 pktbp
= pktbp
+ BPF_WORDALIGN(pktlen
);
252 pktn
-= (int) BPF_WORDALIGN(pktlen
);
258 putpkt(int fd
, uchar
*buf
, int sz
)
260 return write(fd
, buf
, sz
);
264 getmtu(int fd
, char *name
)
269 s
= socket(AF_INET
, SOCK_RAW
, 0);
271 perror("Can't get mtu");
274 xx
.ifr_addr
.sa_family
= AF_INET
;
275 snprintf(xx
.ifr_name
, sizeof xx
.ifr_name
, "%s", name
);
276 n
= ioctl(s
, SIOCGIFMTU
, &xx
);
278 perror("Can't get mtu");
282 // FreeBSD bpf writes are capped at one PAGESIZE'd mbuf. As such we must
283 // limit our sector count. See FreeBSD PR 205164, OpenAoE/vblade #7.
285 if (xx
.ifr_mtu
> p
) {
299 // Try getting disklabel from block dev
300 if ((n
= ioctl(fd
, DIOCGMEDIASIZE
, &media_size
)) != -1) {
303 // must not be a block special dev
304 if (fstat(fd
, &s
) == -1) {
310 printf("ioctl returned %d\n", n
);
311 printf("%lld bytes\n", size
);