4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015 Joyent, Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/stropts.h>
31 #include <sys/socket.h>
32 #include <sys/socketvar.h>
33 #include <sys/socket_proto.h>
34 #include <sys/sockio.h>
35 #include <sys/strsun.h>
36 #include <sys/kstat.h>
37 #include <sys/modctl.h>
38 #include <sys/policy.h>
39 #include <sys/priv_const.h>
40 #include <sys/tihdr.h>
41 #include <sys/zone.h>
42 #include <sys/time.h>
43 #include <sys/ethernet.h>
44 #include <sys/llc1.h>
45 #include <fs/sockfs/sockcommon.h>
46 #include <net/if.h>
47 #include <inet/ip_arp.h>
48
49 #include <sys/dls.h>
50 #include <sys/mac.h>
51 #include <sys/mac_client.h>
52 #include <sys/mac_provider.h>
53 #include <sys/mac_client_priv.h>
54
55 #include <netpacket/packet.h>
56
57 static void pfp_close(mac_handle_t, mac_client_handle_t);
58 static int pfp_dl_to_arphrd(int);
59 static int pfp_getpacket_sockopt(sock_lower_handle_t, int, void *,
60 socklen_t *);
61 static int pfp_ifreq_getlinkid(intptr_t, struct ifreq *, datalink_id_t *, int);
62 static int pfp_lifreq_getlinkid(intptr_t, struct lifreq *, datalink_id_t *,
63 int);
64 static int pfp_open_index(int, mac_handle_t *, mac_client_handle_t *,
65 cred_t *);
66 static void pfp_packet(void *, mac_resource_handle_t, mblk_t *, boolean_t);
67 static void pfp_release_bpf(struct pfpsock *);
68 static int pfp_set_promisc(struct pfpsock *, mac_client_promisc_type_t);
69 static int pfp_setsocket_sockopt(sock_lower_handle_t, int, const void *,
70 socklen_t);
71 static int pfp_setpacket_sockopt(sock_lower_handle_t, int, const void *,
72 socklen_t);
73
431 if (hdr.mhi_pktsize == 0)
432 hdr.mhi_pktsize = msgdsize(mp);
433
434 /*
435 * If a BPF filter is present, pass the raw packet into that.
436 * A failed match will result in zero being returned, indicating
437 * that this socket is not interested in the packet.
438 */
439 if (ps->ps_bpf.bf_len != 0) {
440 uchar_t *buffer;
441 int buflen;
442
443 buflen = MBLKL(mp);
444 if (hdr.mhi_pktsize == buflen) {
445 buffer = mp->b_rptr;
446 } else {
447 buflen = 0;
448 buffer = (uchar_t *)mp;
449 }
450 rw_enter(&ps->ps_bpflock, RW_READER);
451 if (bpf_filter(ps->ps_bpf.bf_insns, buffer,
452 hdr.mhi_pktsize, buflen) == 0) {
453 rw_exit(&ps->ps_bpflock);
454 ps->ps_stats.tp_drops++;
455 ks_stats.kp_recv_filtered.value.ui64++;
456 freemsg(mp);
457 return;
458 }
459 rw_exit(&ps->ps_bpflock);
460 }
461
462 if (ps->ps_type == SOCK_DGRAM) {
463 /*
464 * SOCK_DGRAM socket expect a "layer 3" packet, so advance
465 * past the link layer header.
466 */
467 mp->b_rptr += hdr.mhi_hdrsize;
468 hdr.mhi_pktsize -= hdr.mhi_hdrsize;
469 }
470
471 tusz = sizeof (struct T_unitdata_ind) + sizeof (struct sockaddr_ll);
1319 error = EINVAL;
1320 break;
1321 }
1322
1323 return (error);
1324 }
1325
1326 /*
1327 * There are only two special setsockopt's for SOL_SOCKET with PF_PACKET:
1328 * SO_ATTACH_FILTER and SO_DETACH_FILTER.
1329 *
1330 * Both of these setsockopt values are candidates for being handled by the
1331 * socket layer itself in future, however this requires understanding how
1332 * they would interact with all other sockets.
1333 */
1334 static int
1335 pfp_setsocket_sockopt(sock_lower_handle_t handle, int option_name,
1336 const void *optval, socklen_t optlen)
1337 {
1338 struct bpf_program prog;
1339 struct bpf_insn *fcode;
1340 struct pfpsock *ps;
1341 struct sock_proto_props sopp;
1342 int error = 0;
1343 int size;
1344
1345 ps = (struct pfpsock *)handle;
1346
1347 switch (option_name) {
1348 case SO_ATTACH_FILTER :
1349 #ifdef _LP64
1350 if (optlen == sizeof (struct bpf_program32)) {
1351 struct bpf_program32 prog32;
1352
1353 bcopy(optval, &prog32, sizeof (prog32));
1354 prog.bf_len = prog32.bf_len;
1355 prog.bf_insns = (void *)(uint64_t)prog32.bf_insns;
1356 } else
1357 #endif
1358 if (optlen == sizeof (struct bpf_program)) {
1359 bcopy(optval, &prog, sizeof (prog));
1360 } else if (optlen != sizeof (struct bpf_program)) {
1361 return (EINVAL);
1362 }
1363 if (prog.bf_len > BPF_MAXINSNS)
1364 return (EINVAL);
1365
1366 size = prog.bf_len * sizeof (*prog.bf_insns);
1367 fcode = kmem_alloc(size, KM_SLEEP);
1368 if (ddi_copyin(prog.bf_insns, fcode, size, 0) != 0) {
1369 kmem_free(fcode, size);
1370 return (EFAULT);
1371 }
1372
1373 if (bpf_validate(fcode, (int)prog.bf_len)) {
1374 rw_enter(&ps->ps_bpflock, RW_WRITER);
1375 pfp_release_bpf(ps);
1376 ps->ps_bpf.bf_insns = fcode;
1377 ps->ps_bpf.bf_len = size;
1378 rw_exit(&ps->ps_bpflock);
1379
1380 return (0);
1381 }
1382 kmem_free(fcode, size);
1383 error = EINVAL;
1384 break;
1385
1386 case SO_DETACH_FILTER :
1387 pfp_release_bpf(ps);
1388 break;
1389
1390 case SO_RCVBUF :
1391 size = *(int32_t *)optval;
1392 if (size > sockmod_pfp_rcvbuf_max || size < 0)
1393 return (ENOBUFS);
1394 sopp.sopp_flags = SOCKOPT_RCVHIWAT;
1395 sopp.sopp_rxhiwat = size;
1396 ps->ps_upcalls->su_set_proto_props(ps->ps_upper, &sopp);
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2016 Joyent, Inc.
25 */
26
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/stropts.h>
31 #include <sys/socket.h>
32 #include <sys/socketvar.h>
33 #include <sys/socket_proto.h>
34 #include <sys/sockio.h>
35 #include <sys/strsun.h>
36 #include <sys/kstat.h>
37 #include <sys/modctl.h>
38 #include <sys/policy.h>
39 #include <sys/priv_const.h>
40 #include <sys/tihdr.h>
41 #include <sys/zone.h>
42 #include <sys/time.h>
43 #include <sys/ethernet.h>
44 #include <sys/llc1.h>
45 #include <fs/sockfs/sockcommon.h>
46 #include <net/if.h>
47 #include <inet/ip_arp.h>
48
49 #include <sys/dls.h>
50 #include <sys/mac.h>
51 #include <sys/mac_client.h>
52 #include <sys/mac_provider.h>
53 #include <sys/mac_client_priv.h>
54 #include <inet/bpf.h>
55
56 #include <netpacket/packet.h>
57
58 static void pfp_close(mac_handle_t, mac_client_handle_t);
59 static int pfp_dl_to_arphrd(int);
60 static int pfp_getpacket_sockopt(sock_lower_handle_t, int, void *,
61 socklen_t *);
62 static int pfp_ifreq_getlinkid(intptr_t, struct ifreq *, datalink_id_t *, int);
63 static int pfp_lifreq_getlinkid(intptr_t, struct lifreq *, datalink_id_t *,
64 int);
65 static int pfp_open_index(int, mac_handle_t *, mac_client_handle_t *,
66 cred_t *);
67 static void pfp_packet(void *, mac_resource_handle_t, mblk_t *, boolean_t);
68 static void pfp_release_bpf(struct pfpsock *);
69 static int pfp_set_promisc(struct pfpsock *, mac_client_promisc_type_t);
70 static int pfp_setsocket_sockopt(sock_lower_handle_t, int, const void *,
71 socklen_t);
72 static int pfp_setpacket_sockopt(sock_lower_handle_t, int, const void *,
73 socklen_t);
74
432 if (hdr.mhi_pktsize == 0)
433 hdr.mhi_pktsize = msgdsize(mp);
434
435 /*
436 * If a BPF filter is present, pass the raw packet into that.
437 * A failed match will result in zero being returned, indicating
438 * that this socket is not interested in the packet.
439 */
440 if (ps->ps_bpf.bf_len != 0) {
441 uchar_t *buffer;
442 int buflen;
443
444 buflen = MBLKL(mp);
445 if (hdr.mhi_pktsize == buflen) {
446 buffer = mp->b_rptr;
447 } else {
448 buflen = 0;
449 buffer = (uchar_t *)mp;
450 }
451 rw_enter(&ps->ps_bpflock, RW_READER);
452 if (ip_bpf_filter((ip_bpf_insn_t *)ps->ps_bpf.bf_insns, buffer,
453 hdr.mhi_pktsize, buflen) == 0) {
454 rw_exit(&ps->ps_bpflock);
455 ps->ps_stats.tp_drops++;
456 ks_stats.kp_recv_filtered.value.ui64++;
457 freemsg(mp);
458 return;
459 }
460 rw_exit(&ps->ps_bpflock);
461 }
462
463 if (ps->ps_type == SOCK_DGRAM) {
464 /*
465 * SOCK_DGRAM socket expect a "layer 3" packet, so advance
466 * past the link layer header.
467 */
468 mp->b_rptr += hdr.mhi_hdrsize;
469 hdr.mhi_pktsize -= hdr.mhi_hdrsize;
470 }
471
472 tusz = sizeof (struct T_unitdata_ind) + sizeof (struct sockaddr_ll);
1320 error = EINVAL;
1321 break;
1322 }
1323
1324 return (error);
1325 }
1326
1327 /*
1328 * There are only two special setsockopt's for SOL_SOCKET with PF_PACKET:
1329 * SO_ATTACH_FILTER and SO_DETACH_FILTER.
1330 *
1331 * Both of these setsockopt values are candidates for being handled by the
1332 * socket layer itself in future, however this requires understanding how
1333 * they would interact with all other sockets.
1334 */
1335 static int
1336 pfp_setsocket_sockopt(sock_lower_handle_t handle, int option_name,
1337 const void *optval, socklen_t optlen)
1338 {
1339 struct bpf_program prog;
1340 ip_bpf_insn_t *fcode;
1341 struct pfpsock *ps;
1342 struct sock_proto_props sopp;
1343 int error = 0;
1344 int size;
1345
1346 ps = (struct pfpsock *)handle;
1347
1348 switch (option_name) {
1349 case SO_ATTACH_FILTER :
1350 #ifdef _LP64
1351 if (optlen == sizeof (struct bpf_program32)) {
1352 struct bpf_program32 prog32;
1353
1354 bcopy(optval, &prog32, sizeof (prog32));
1355 prog.bf_len = prog32.bf_len;
1356 prog.bf_insns = (void *)(uint64_t)prog32.bf_insns;
1357 } else
1358 #endif
1359 if (optlen == sizeof (struct bpf_program)) {
1360 bcopy(optval, &prog, sizeof (prog));
1361 } else if (optlen != sizeof (struct bpf_program)) {
1362 return (EINVAL);
1363 }
1364 if (prog.bf_len > BPF_MAXINSNS)
1365 return (EINVAL);
1366
1367 size = prog.bf_len * sizeof (*prog.bf_insns);
1368 fcode = kmem_alloc(size, KM_SLEEP);
1369 if (ddi_copyin(prog.bf_insns, fcode, size, 0) != 0) {
1370 kmem_free(fcode, size);
1371 return (EFAULT);
1372 }
1373
1374 if (ip_bpf_validate(fcode, prog.bf_len)) {
1375 rw_enter(&ps->ps_bpflock, RW_WRITER);
1376 pfp_release_bpf(ps);
1377 ps->ps_bpf.bf_insns = (struct bpf_insn *)fcode;
1378 ps->ps_bpf.bf_len = size;
1379 rw_exit(&ps->ps_bpflock);
1380
1381 return (0);
1382 }
1383 kmem_free(fcode, size);
1384 error = EINVAL;
1385 break;
1386
1387 case SO_DETACH_FILTER :
1388 pfp_release_bpf(ps);
1389 break;
1390
1391 case SO_RCVBUF :
1392 size = *(int32_t *)optval;
1393 if (size > sockmod_pfp_rcvbuf_max || size < 0)
1394 return (ENOBUFS);
1395 sopp.sopp_flags = SOCKOPT_RCVHIWAT;
1396 sopp.sopp_rxhiwat = size;
1397 ps->ps_upcalls->su_set_proto_props(ps->ps_upper, &sopp);
|