1 /*
2 * Copyright (c) 2023-2024 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <sys/param.h>
30 #include <sys/protosw.h>
31 #include <sys/systm.h>
32 #include <sys/sysctl.h>
33
34 #include <kern/bits.h>
35
36 #include <netinet/ip.h>
37 #include <netinet/ip6.h>
38
39 #include <netinet/inp_log.h>
40 #include <netinet/in_pcb.h>
41
42 #include <netinet/udp_log.h>
43 #include <netinet/udp_var.h>
44
45 SYSCTL_NODE(_net_inet_udp, OID_AUTO, log, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
46 "UDP");
47
48 #if (DEVELOPMENT || DEBUG)
49 #define UDP_LOG_ENABLE_DEFAULT \
50 (ULEF_CONNECT | ULEF_DST_LOCAL | ULEF_DST_GW)
51 #else /* (DEVELOPMENT || DEBUG) */
52 #define UDP_LOG_ENABLE_DEFAULT \
53 (ULEF_CONNECT | ULEF_DST_LOCAL | ULEF_DST_GW)
54 #endif /* (DEVELOPMENT || DEBUG) */
55
56 uint32_t udp_log_enable_flags = UDP_LOG_ENABLE_DEFAULT;
57 SYSCTL_UINT(_net_inet_udp_log, OID_AUTO, enable,
58 CTLFLAG_RW | CTLFLAG_LOCKED, &udp_log_enable_flags, 0, "");
59
60
61 /*
62 * The following is a help to describe the values of the flags
63 */
64 #define X(name, value, description, ...) #description ":" #value " "
65 SYSCTL_STRING(_net_inet_udp_log, OID_AUTO, enable_usage, CTLFLAG_RD | CTLFLAG_LOCKED,
66 UDP_ENABLE_FLAG_LIST, 0, "");
67 #undef X
68
69 /*
70 *
71 */
72 static int sysctl_udp_log_port SYSCTL_HANDLER_ARGS;
73
74 int udp_log_bind_anon_port = 0;
75 SYSCTL_INT(_net_inet_udp_log, OID_AUTO, bind_anon_port,
76 CTLFLAG_RW | CTLFLAG_LOCKED, &udp_log_bind_anon_port, 0, "");
77
78 int udp_log_local_port_included = 0;
79 SYSCTL_PROC(_net_inet_udp_log, OID_AUTO, local_port_included,
80 CTLFLAG_RW | CTLFLAG_LOCKED,
81 &udp_log_local_port_included, 0, &sysctl_udp_log_port, "I", "");
82
83 int udp_log_remote_port_included = 0;
84 SYSCTL_PROC(_net_inet_udp_log, OID_AUTO, remote_port_included,
85 CTLFLAG_RW | CTLFLAG_LOCKED,
86 &udp_log_remote_port_included, 0, &sysctl_udp_log_port, "I", "");
87
88 int udp_log_local_port_excluded = 0;
89 SYSCTL_PROC(_net_inet_udp_log, OID_AUTO, local_port_excluded,
90 CTLFLAG_RW | CTLFLAG_LOCKED,
91 &udp_log_local_port_excluded, 0, &sysctl_udp_log_port, "I", "");
92
93 int udp_log_remote_port_excluded = 0;
94 SYSCTL_PROC(_net_inet_udp_log, OID_AUTO, remote_port_excluded,
95 CTLFLAG_RW | CTLFLAG_LOCKED,
96 &udp_log_remote_port_excluded, 0, &sysctl_udp_log_port, "I", "");
97
98 #define UDP_LOG_RATE_LIMIT 1000
99 static unsigned int udp_log_rate_limit = UDP_LOG_RATE_LIMIT;
100 SYSCTL_UINT(_net_inet_udp_log, OID_AUTO, rate_limit,
101 CTLFLAG_RW | CTLFLAG_LOCKED, &udp_log_rate_limit, 0, "");
102
103 /* 1 minute by default */
104 #define UDP_LOG_RATE_DURATION 60
105 static unsigned int udp_log_rate_duration = UDP_LOG_RATE_DURATION;
106 SYSCTL_UINT(_net_inet_udp_log, OID_AUTO, rate_duration,
107 CTLFLAG_RW | CTLFLAG_LOCKED, &udp_log_rate_duration, 0, "");
108
109 static unsigned long udp_log_rate_max = 0;
110 SYSCTL_ULONG(_net_inet_udp_log, OID_AUTO, rate_max,
111 CTLFLAG_RD | CTLFLAG_LOCKED, &udp_log_rate_max, "");
112
113 static unsigned long udp_log_rate_exceeded_total = 0;
114 SYSCTL_ULONG(_net_inet_udp_log, OID_AUTO, rate_exceeded_total,
115 CTLFLAG_RD | CTLFLAG_LOCKED, &udp_log_rate_exceeded_total, "");
116
117 static unsigned long udp_log_rate_current = 0;
118 SYSCTL_ULONG(_net_inet_udp_log, OID_AUTO, rate_current,
119 CTLFLAG_RD | CTLFLAG_LOCKED, &udp_log_rate_current, "");
120
121 static bool udp_log_rate_exceeded_logged = false;
122
123 static uint64_t udp_log_current_period = 0;
124
125 #define ADDRESS_STR_LEN (MAX_IPv6_STR_LEN + 6)
126
127
128 #define UDP_LOG_COMMON_FMT \
129 "[%s:%u<->%s:%u] " \
130 "interface: %s " \
131 "(skipped: %lu)\n"
132
133 #define UDP_LOG_COMMON_ARGS \
134 laddr_buf, ntohs(local_port), faddr_buf, ntohs(foreign_port), \
135 ifp != NULL ? if_name(ifp) : "", \
136 udp_log_rate_exceeded_total
137
138 #define UDP_LOG_COMMON_PCB_FMT \
139 UDP_LOG_COMMON_FMT \
140 "so_gencnt: %llu " \
141 "so_state: 0x%04x " \
142 "process: %s:%u "
143
144 #define UDP_LOG_COMMON_PCB_ARGS \
145 UDP_LOG_COMMON_ARGS, \
146 so != NULL ? so->so_gencnt : 0, \
147 so != NULL ? so->so_state : 0, \
148 inp->inp_last_proc_name, so->last_pid
149
150 /*
151 * Returns true when above the rate limit
152 */
153 static bool
udp_log_is_rate_limited(void)154 udp_log_is_rate_limited(void)
155 {
156 uint64_t current_net_period = net_uptime();
157
158 /* When set to zero it means to reset to default */
159 if (udp_log_rate_duration == 0) {
160 udp_log_rate_duration = UDP_LOG_RATE_DURATION;
161 }
162 if (udp_log_rate_limit == 0) {
163 udp_log_rate_duration = UDP_LOG_RATE_LIMIT;
164 }
165
166 if (current_net_period > udp_log_current_period + udp_log_rate_duration) {
167 if (udp_log_rate_current > udp_log_rate_max) {
168 udp_log_rate_max = udp_log_rate_current;
169 }
170 udp_log_current_period = current_net_period;
171 udp_log_rate_current = 0;
172 udp_log_rate_exceeded_logged = false;
173 }
174
175 udp_log_rate_current += 1;
176
177 if (udp_log_rate_current > (unsigned long) udp_log_rate_limit) {
178 udp_log_rate_exceeded_total += 1;
179 return true;
180 }
181
182 return false;
183 }
184
185 static bool
udp_log_port_allowed(struct inpcb * inp)186 udp_log_port_allowed(struct inpcb *inp)
187 {
188 if (udp_log_local_port_included != 0 || udp_log_remote_port_included != 0) {
189 if (ntohs(inp->inp_lport) == udp_log_local_port_included ||
190 ntohs(inp->inp_fport) == udp_log_remote_port_included) {
191 return true;
192 } else {
193 return false;
194 }
195 }
196 if (udp_log_local_port_excluded != 0 || udp_log_remote_port_excluded != 0) {
197 if (ntohs(inp->inp_lport) == udp_log_local_port_excluded ||
198 ntohs(inp->inp_fport) == udp_log_remote_port_excluded) {
199 return false;
200 }
201 }
202
203 return true;
204 }
205
206 static inline void
udp_log_common(struct inpcb * inp,const char * event,int error)207 udp_log_common(struct inpcb *inp, const char *event, int error)
208 {
209 struct socket *so = inp->inp_socket;
210 struct ifnet *ifp;
211 char laddr_buf[ADDRESS_STR_LEN];
212 char faddr_buf[ADDRESS_STR_LEN];
213 in_port_t local_port;
214 in_port_t foreign_port;
215
216 /* Clear the logging flags as one may reconnect an UDP socket */
217 inp->inp_flags2 &= ~INP2_LOGGED_SUMMARY;
218 inp->inp_flags2 |= INP2_LOGGING_ENABLED;
219
220 so = inp->inp_socket;
221
222 local_port = inp->inp_lport;
223 foreign_port = inp->inp_fport;
224
225 ifp = inp->inp_last_outifp != NULL ? inp->inp_last_outifp :
226 inp->inp_boundifp != NULL ? inp->inp_boundifp : NULL;
227
228 inp_log_addresses(inp, laddr_buf, sizeof(laddr_buf), faddr_buf, sizeof(faddr_buf));
229
230 #define UDP_LOG_CONNECTION_FMT \
231 "udp %s: " \
232 UDP_LOG_COMMON_PCB_FMT \
233 "bytes in/out: %llu/%llu " \
234 "pkts in/out: %llu/%llu " \
235 "error: %d " \
236 "so_error: %d " \
237 "svc/tc: %u " \
238 "flow: 0x%x"
239
240 #define UDP_LOG_CONNECTION_ARGS \
241 event, \
242 UDP_LOG_COMMON_PCB_ARGS, \
243 inp->inp_mstat.ms_total.ts_rxbytes, inp->inp_mstat.ms_total.ts_txbytes, \
244 inp->inp_mstat.ms_total.ts_rxpackets, inp->inp_mstat.ms_total.ts_txpackets, \
245 error, \
246 so->so_error, \
247 (so->so_flags1 & SOF1_TC_NET_SERV_TYPE) ? so->so_netsvctype : so->so_traffic_class, \
248 inp->inp_flowhash
249
250 os_log(OS_LOG_DEFAULT, UDP_LOG_CONNECTION_FMT,
251 UDP_LOG_CONNECTION_ARGS);
252
253 #undef UDP_LOG_CONNECTION_FMT
254 #undef UDP_LOG_CONNECTION_ARGS
255 }
256
257 __attribute__((noinline))
258 void
udp_log_bind(struct inpcb * inp,int error)259 udp_log_bind(struct inpcb *inp, int error)
260 {
261 if (inp == NULL || inp->inp_socket == NULL) {
262 return;
263 }
264 /* Do not log too much */
265 if (udp_log_is_rate_limited()) {
266 return;
267 }
268 /* Allow logging of bind errors regardless of the port */
269 if (error == 0) {
270 if (udp_log_bind_anon_port == 0 && (inp->inp_flags & INP_ANONPORT) != 0) {
271 return;
272 }
273 if (udp_log_port_allowed(inp) == false) {
274 return;
275 }
276 }
277 udp_log_common(inp, "bind", error);
278 }
279
280 __attribute__((noinline))
281 void
udp_log_connect(struct inpcb * inp,int error)282 udp_log_connect(struct inpcb *inp, int error)
283 {
284 if (inp == NULL || inp->inp_socket == NULL) {
285 return;
286 }
287 /* Do not log too much */
288 if (udp_log_is_rate_limited()) {
289 return;
290 }
291 /* Allow logging of connection errors regardless of the port */
292 if (error == 0 && udp_log_port_allowed(inp) == false) {
293 return;
294 }
295 udp_log_common(inp, "connect", error);
296 }
297
298 __attribute__((noinline))
299 void
udp_log_connection_summary(struct inpcb * inp)300 udp_log_connection_summary(struct inpcb *inp)
301 {
302 struct socket *so;
303 struct ifnet *ifp;
304 clock_sec_t duration_secs = 0;
305 clock_usec_t duration_microsecs = 0;
306 clock_sec_t connection_secs = 0;
307 clock_usec_t connection_microsecs = 0;
308 char laddr_buf[ADDRESS_STR_LEN];
309 char faddr_buf[ADDRESS_STR_LEN];
310 in_port_t local_port;
311 in_port_t foreign_port;
312
313 if (inp == NULL || inp->inp_socket == NULL) {
314 return;
315 }
316 if ((inp->inp_flags2 & INP2_LOGGING_ENABLED) == 0) {
317 return;
318 }
319 /* Make sure the summary is logged once */
320 if (inp->inp_flags2 & INP2_LOGGED_SUMMARY) {
321 return;
322 }
323 inp->inp_flags2 |= INP2_LOGGED_SUMMARY;
324 inp->inp_flags2 &= ~INP2_LOGGING_ENABLED;
325
326 /* UDP can be reconnected so clear the destination flags */
327 inp->inp_log_flags = 0;
328
329 /* Do not log too much */
330 if (udp_log_is_rate_limited()) {
331 return;
332 }
333 so = inp->inp_socket;
334
335 local_port = inp->inp_lport;
336 foreign_port = inp->inp_fport;
337
338 /*
339 * inp_start_timestamp is when the UDP socket was open.
340 *
341 * inp_connect_timestamp is when the connection started on
342 */
343 uint64_t now = mach_continuous_time();
344 if (inp->inp_start_timestamp > 0) {
345 uint64_t duration = now - inp->inp_start_timestamp;
346
347 absolutetime_to_microtime(duration, &duration_secs, &duration_microsecs);
348 }
349 if (inp->inp_connect_timestamp > 0) {
350 uint64_t duration = now - inp->inp_connect_timestamp;
351
352 absolutetime_to_microtime(duration, &connection_secs, &connection_microsecs);
353 }
354
355 ifp = inp->inp_last_outifp != NULL ? inp->inp_last_outifp :
356 inp->inp_boundifp != NULL ? inp->inp_boundifp : NULL;
357
358 inp_log_addresses(inp, laddr_buf, sizeof(laddr_buf), faddr_buf, sizeof(faddr_buf));
359
360 /*
361 * Need to use 2 log messages because the size of the summary
362 */
363
364 #define UDP_LOG_CONNECTION_SUMMARY_FMT \
365 "udp_connection_summary " \
366 UDP_LOG_COMMON_PCB_FMT \
367 "Duration: %lu.%03d sec " \
368 "Conn_Time: %lu.%03d sec " \
369 "bytes in/out: %llu/%llu " \
370 "pkts in/out: %llu/%llu " \
371 "rxnospace pkts/bytes: %llu/%llu " \
372 "so_error: %d " \
373 "svc/tc: %u " \
374 "flow: 0x%x " \
375 "flowctl: %lluus (%llux) "
376
377 #define UDP_LOG_CONNECTION_SUMMARY_ARGS \
378 UDP_LOG_COMMON_PCB_ARGS, \
379 duration_secs, duration_microsecs / 1000, \
380 connection_secs, connection_microsecs / 1000, \
381 inp->inp_mstat.ms_total.ts_rxbytes, inp->inp_mstat.ms_total.ts_txbytes, \
382 inp->inp_mstat.ms_total.ts_rxpackets, inp->inp_mstat.ms_total.ts_txpackets, \
383 so->so_tc_stats[SO_STATS_SBNOSPACE].rxpackets, \
384 so->so_tc_stats[SO_STATS_SBNOSPACE].rxbytes, \
385 so->so_error, \
386 (so->so_flags1 & SOF1_TC_NET_SERV_TYPE) ? so->so_netsvctype : so->so_traffic_class, \
387 inp->inp_flowhash, \
388 inp->inp_fadv_total_time, \
389 inp->inp_fadv_cnt
390
391 os_log(OS_LOG_DEFAULT, UDP_LOG_CONNECTION_SUMMARY_FMT,
392 UDP_LOG_CONNECTION_SUMMARY_ARGS);
393 #undef UDP_LOG_CONNECTION_SUMMARY_FMT
394 #undef UDP_LOG_CONNECTION_SUMMARY_ARGS
395 }
396
397 __attribute__((noinline))
398 void
udp_log_message(const char * func_name,int line_no,struct inpcb * inp,const char * format,...)399 udp_log_message(const char *func_name, int line_no, struct inpcb *inp, const char *format, ...)
400 {
401 struct socket *so;
402 struct ifnet *ifp;
403 char laddr_buf[ADDRESS_STR_LEN];
404 char faddr_buf[ADDRESS_STR_LEN];
405 in_port_t local_port;
406 in_port_t foreign_port;
407 char message[256];
408
409 if (inp == NULL || inp->inp_socket == NULL) {
410 return;
411 }
412
413 /* Do not log too much */
414 if (udp_log_is_rate_limited()) {
415 return;
416 }
417
418 if (!udp_log_port_allowed(inp)) {
419 return;
420 }
421
422 so = inp->inp_socket;
423
424 local_port = inp->inp_lport;
425 foreign_port = inp->inp_fport;
426
427 ifp = inp->inp_last_outifp != NULL ? inp->inp_last_outifp :
428 inp->inp_boundifp != NULL ? inp->inp_boundifp : NULL;
429
430 inp_log_addresses(inp, laddr_buf, sizeof(laddr_buf), faddr_buf, sizeof(faddr_buf));
431
432 va_list ap;
433 va_start(ap, format);
434 vsnprintf(message, sizeof(message), format, ap);
435 va_end(ap);
436
437 #define UDP_LOG_MESSAGE_FMT \
438 "udp (%s:%d): " \
439 UDP_LOG_COMMON_PCB_FMT \
440 "%s"
441
442 #define UDP_LOG_MESSAGE_ARGS \
443 func_name, line_no, \
444 UDP_LOG_COMMON_PCB_ARGS, \
445 message
446
447 os_log(OS_LOG_DEFAULT, UDP_LOG_MESSAGE_FMT,
448 UDP_LOG_MESSAGE_ARGS);
449
450 #undef UDP_LOG_MESSAGE_FMT
451 #undef UDP_LOG_MESSAGE_ARGS
452 }
453
454 static bool
udp_log_pkt_addresses(void * hdr,bool outgoing,char * __sized_by (lbuflen)lbuf,socklen_t lbuflen,char * __sized_by (fbuflen)fbuf,socklen_t fbuflen)455 udp_log_pkt_addresses(void *hdr, bool outgoing,
456 char *__sized_by(lbuflen) lbuf, socklen_t lbuflen,
457 char *__sized_by(fbuflen) fbuf, socklen_t fbuflen)
458 {
459 bool isipv6;
460
461 isipv6 = (((struct ip *)hdr)->ip_v == 6);
462
463 if (isipv6) {
464 struct ip6_hdr *ip6 = (struct ip6_hdr *)hdr;
465 struct in6_addr src_addr6 = ip6->ip6_src;
466 struct in6_addr dst_addr6 = ip6->ip6_dst;
467
468 #pragma clang diagnostic push
469 #pragma clang diagnostic ignored "-Waddress-of-packed-member"
470 if (memcmp(&src_addr6, &in6addr_loopback, sizeof(struct in6_addr)) == 0 ||
471 memcmp(&dst_addr6, &in6addr_loopback, sizeof(struct in6_addr)) == 0) {
472 if (!(udp_log_enable_flags & ULEF_DST_LOOPBACK)) {
473 return false;
474 }
475 }
476 #pragma clang diagnostic pop
477
478 if (IN6_IS_ADDR_LINKLOCAL(&src_addr6)) {
479 src_addr6.s6_addr16[1] = 0;
480 }
481 if (IN6_IS_ADDR_LINKLOCAL(&dst_addr6)) {
482 dst_addr6.s6_addr16[1] = 0;
483 }
484
485 if (inp_log_privacy != 0) {
486 strlcpy(lbuf, "<IPv6-redacted>", lbuflen);
487 strlcpy(fbuf, "<IPv6-redacted>", fbuflen);
488 } else if (outgoing) {
489 inet_ntop(AF_INET6, &src_addr6, lbuf, lbuflen);
490 inet_ntop(AF_INET6, &dst_addr6, fbuf, fbuflen);
491 } else {
492 inet_ntop(AF_INET6, &dst_addr6, lbuf, lbuflen);
493 inet_ntop(AF_INET6, &src_addr6, fbuf, fbuflen);
494 }
495 } else {
496 struct ip *ip = (struct ip *)hdr;
497
498 if (ntohl(ip->ip_src.s_addr) == INADDR_LOOPBACK ||
499 ntohl(ip->ip_dst.s_addr) == INADDR_LOOPBACK) {
500 if (!(udp_log_enable_flags & ULEF_DST_LOOPBACK)) {
501 return false;
502 }
503 }
504
505 if (inp_log_privacy != 0) {
506 strlcpy(lbuf, "<IPv4-redacted>", lbuflen);
507 strlcpy(fbuf, "<IPv4-redacted>", fbuflen);
508 } else if (outgoing) {
509 inet_ntop(AF_INET, (void *)&ip->ip_src.s_addr, lbuf, lbuflen);
510 inet_ntop(AF_INET, (void *)&ip->ip_dst.s_addr, fbuf, fbuflen);
511 } else {
512 inet_ntop(AF_INET, (void *)&ip->ip_dst.s_addr, lbuf, lbuflen);
513 inet_ntop(AF_INET, (void *)&ip->ip_src.s_addr, fbuf, fbuflen);
514 }
515 }
516 return true;
517 }
518
519 __attribute__((noinline))
520 void
udp_log_drop_pcb(void * hdr,struct udphdr * uh,struct inpcb * inp,bool outgoing,const char * reason)521 udp_log_drop_pcb(void *hdr, struct udphdr *uh, struct inpcb *inp, bool outgoing, const char *reason)
522 {
523 struct socket *so;
524 struct ifnet *ifp;
525 char laddr_buf[ADDRESS_STR_LEN];
526 char faddr_buf[ADDRESS_STR_LEN];
527 in_port_t local_port;
528 in_port_t foreign_port;
529 const char *direction = "";
530
531 if (inp == NULL) {
532 return;
533 }
534 so = inp->inp_socket;
535 if (so == NULL) {
536 return;
537 }
538
539 /* Do not log common drops after the connection termination is logged */
540 if ((inp->inp_flags2 & INP2_LOGGED_SUMMARY) && ((so->so_state & SS_NOFDREF) ||
541 (so->so_flags & SOF_DEFUNCT) || (so->so_state & SS_CANTRCVMORE))) {
542 return;
543 }
544
545 /* Do not log too much */
546 if (udp_log_is_rate_limited()) {
547 return;
548 }
549
550 /* Use the packet addresses when in the data path */
551 if (hdr != NULL && uh != NULL) {
552 if (outgoing) {
553 local_port = uh->uh_sport;
554 foreign_port = uh->uh_dport;
555 direction = "outgoing ";
556 } else {
557 local_port = uh->uh_dport;
558 foreign_port = uh->uh_sport;
559 direction = "incoming ";
560 }
561 (void) udp_log_pkt_addresses(hdr, outgoing, laddr_buf, sizeof(laddr_buf), faddr_buf, sizeof(faddr_buf));
562 } else {
563 local_port = inp->inp_lport;
564 foreign_port = inp->inp_fport;
565 inp_log_addresses(inp, laddr_buf, sizeof(laddr_buf), faddr_buf, sizeof(faddr_buf));
566 }
567
568 ifp = inp->inp_last_outifp != NULL ? inp->inp_last_outifp :
569 inp->inp_boundifp != NULL ? inp->inp_boundifp : NULL;
570
571 #define UDP_LOG_DROP_PCB_FMT \
572 "udp drop %s" \
573 UDP_LOG_COMMON_PCB_FMT \
574 "so_error: %d " \
575 "reason: %s"
576
577 #define UDP_LOG_DROP_PCB_ARGS \
578 direction, \
579 UDP_LOG_COMMON_PCB_ARGS, \
580 so->so_error, \
581 reason
582
583 os_log(OS_LOG_DEFAULT, UDP_LOG_DROP_PCB_FMT,
584 UDP_LOG_DROP_PCB_ARGS);
585 #undef UDP_LOG_DROP_PCB_FMT
586 #undef UDP_LOG_DROP_PCB_ARGS
587 }
588 static int
589 sysctl_udp_log_port SYSCTL_HANDLER_ARGS
590 {
591 #pragma unused(arg1, arg2)
592 int error;
593 int new_value = *(uint16_t *)oidp->oid_arg1;
594
595 error = sysctl_handle_int(oidp, &new_value, 0, req);
596 if (error == 0) {
597 if (new_value < 0 || new_value > UINT16_MAX) {
598 return EINVAL;
599 }
600 *(int *)oidp->oid_arg1 = new_value;
601 }
602 return error;
603 }
604