2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Copyright 2009, 2010 Emmanuel Roullit.
6 * Copyright 2010 Marek Polacek.
7 * Copyright 2013 Tobias Klauser.
8 * Subject to the GPL, version 2.
22 #include <arpa/inet.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
33 #include <sys/resource.h>
34 #include <sys/epoll.h>
35 #include <sys/syscall.h>
36 #include <asm/unistd.h>
39 #include <linux/socket.h>
40 #include <linux/types.h>
42 #include <linux/if_ether.h>
43 #include <linux/if_packet.h>
44 #include <linux/sockios.h>
45 #include <netinet/tcp.h>
46 #include <netinet/udp.h>
54 #define IOPRIO_CLASS_SHIFT 13
64 ioprio_who_process
= 1,
69 static const char *const to_prio
[] = {
70 "none", "realtime", "best-effort", "idle",
73 static const char *const sock_mem
[] = {
74 "/proc/sys/net/core/rmem_max",
75 "/proc/sys/net/core/rmem_default",
76 "/proc/sys/net/core/wmem_max",
77 "/proc/sys/net/core/wmem_default",
84 if (unlikely(af
!= AF_INET
&& af
!= AF_INET6
)) {
85 whine("Wrong AF socket type! Falling back to AF_INET\n");
89 sock
= socket(af
, SOCK_DGRAM
, 0);
90 if (unlikely(sock
< 0))
91 panic("Creation AF socket failed!\n");
98 int sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
99 if (unlikely(sock
< 0))
100 panic("Creation of PF socket failed!\n");
105 void set_sock_prio(int fd
, int prio
)
108 setsockopt(fd
, SOL_SOCKET
, SO_PRIORITY
, &val
, sizeof(val
));
111 void set_udp_cork(int fd
)
114 setsockopt(fd
, IPPROTO_UDP
, UDP_CORK
, &state
, sizeof(state
));
117 void set_udp_uncork(int fd
)
120 setsockopt(fd
, IPPROTO_UDP
, UDP_CORK
, &state
, sizeof(state
));
123 void set_tcp_cork(int fd
)
126 setsockopt(fd
, IPPROTO_TCP
, TCP_CORK
, &state
, sizeof(state
));
129 void set_tcp_uncork(int fd
)
132 setsockopt(fd
, IPPROTO_TCP
, TCP_CORK
, &state
, sizeof(state
));
135 void set_sock_cork(int fd
, int udp
)
143 void set_sock_uncork(int fd
, int udp
)
151 int set_nonblocking(int fd
)
153 int ret
= fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFD
, 0) | O_NONBLOCK
);
154 if (unlikely(ret
< 0))
155 panic("Cannot fcntl!\n");
160 int set_nonblocking_sloppy(int fd
)
162 return fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFD
, 0) | O_NONBLOCK
);
165 void set_socket_keepalive(int fd
)
168 setsockopt(fd
, SOL_SOCKET
, SO_KEEPALIVE
, &one
, sizeof(one
));
171 void set_tcp_nodelay(int fd
)
174 setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &one
, sizeof(one
));
177 int set_ipv6_only(int fd
)
180 return setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &one
, sizeof(one
));
183 int set_reuseaddr(int fd
)
187 ret
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof (one
));
188 if (unlikely(ret
< 0))
189 panic("Cannot reuse addr!\n");
194 void set_mtu_disc_dont(int fd
)
196 int mtu
= IP_PMTUDISC_DONT
;
197 setsockopt(fd
, SOL_IP
, IP_MTU_DISCOVER
, &mtu
, sizeof(mtu
));
200 void set_epoll_descriptor(int fd_epoll
, int action
, int fd_toadd
, int events
)
203 struct epoll_event ev
;
205 memset(&ev
, 0, sizeof(ev
));
207 ev
.data
.fd
= fd_toadd
;
209 ret
= epoll_ctl(fd_epoll
, action
, fd_toadd
, &ev
);
211 panic("Cannot add socket for epoll!\n");
214 int set_epoll_descriptor2(int fd_epoll
, int action
, int fd_toadd
, int events
)
216 struct epoll_event ev
;
218 memset(&ev
, 0, sizeof(ev
));
220 ev
.data
.fd
= fd_toadd
;
222 return epoll_ctl(fd_epoll
, action
, fd_toadd
, &ev
);
225 u32
wireless_bitrate(const char *ifname
)
227 int sock
, ret
, rate_in_mbit
;
230 sock
= af_socket(AF_INET
);
232 memset(&iwr
, 0, sizeof(iwr
));
233 strlcpy(iwr
.ifr_name
, ifname
, IFNAMSIZ
);
235 ret
= ioctl(sock
, SIOCGIWRATE
, &iwr
);
237 rate_in_mbit
= iwr
.u
.bitrate
.value
/ 1000000;
246 int adjust_dbm_level(int in_dbm
, int dbm_val
)
251 return dbm_val
- 0x100;
254 void drop_privileges(bool enforce
, uid_t uid
, gid_t gid
)
258 panic("Uid cannot be the same as the current user!\n");
260 panic("Gid cannot be the same as the current user!\n");
262 if (setgid(gid
) != 0)
263 panic("Unable to drop group privileges: %s!\n", strerror(errno
));
264 if (setuid(uid
) != 0)
265 panic("Unable to drop user privileges: %s!\n", strerror(errno
));
268 int get_system_socket_mem(int which
)
272 const char *file
= sock_mem
[which
];
275 fd
= open(file
, O_RDONLY
);
279 ret
= read(fd
, buff
, sizeof(buff
));
287 void set_system_socket_mem(int which
, int val
)
290 const char *file
= sock_mem
[which
];
294 fd
= open(file
, O_WRONLY
);
298 memset(buff
, 0, sizeof(buff
));
299 slprintf(buff
, sizeof(buff
), "%d", val
);
301 ret
= write(fd
, buff
, strlen(buff
));
307 int wireless_sigqual(const char *ifname
, struct iw_statistics
*stats
)
312 sock
= af_socket(AF_INET
);
314 memset(&iwr
, 0, sizeof(iwr
));
315 strlcpy(iwr
.ifr_name
, ifname
, IFNAMSIZ
);
317 iwr
.u
.data
.pointer
= (caddr_t
) stats
;
318 iwr
.u
.data
.length
= sizeof(*stats
);
319 iwr
.u
.data
.flags
= 1;
321 ret
= ioctl(sock
, SIOCGIWSTATS
, &iwr
);
328 int wireless_rangemax_sigqual(const char *ifname
)
330 int ret
, sock
, sigqual
;
332 struct iw_range iwrange
;
334 sock
= af_socket(AF_INET
);
336 memset(&iwrange
, 0, sizeof(iwrange
));
338 memset(&iwr
, 0, sizeof(iwr
));
339 strlcpy(iwr
.ifr_name
, ifname
, IFNAMSIZ
);
341 iwr
.u
.data
.pointer
= (caddr_t
) &iwrange
;
342 iwr
.u
.data
.length
= sizeof(iwrange
);
343 iwr
.u
.data
.flags
= 0;
345 ret
= ioctl(sock
, SIOCGIWRANGE
, &iwr
);
347 sigqual
= iwrange
.max_qual
.qual
;
356 u32
ethtool_bitrate(const char *ifname
)
358 int ret
, sock
, bitrate
;
360 struct ethtool_cmd ecmd
;
362 sock
= af_socket(AF_INET
);
364 memset(&ecmd
, 0, sizeof(ecmd
));
366 memset(&ifr
, 0, sizeof(ifr
));
367 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
369 ecmd
.cmd
= ETHTOOL_GSET
;
370 ifr
.ifr_data
= (char *) &ecmd
;
372 ret
= ioctl(sock
, SIOCETHTOOL
, &ifr
);
378 switch (ecmd
.speed
) {
384 bitrate
= ecmd
.speed
;
396 int ethtool_link(const char *ifname
)
400 struct ethtool_value ecmd
;
402 sock
= af_socket(AF_INET
);
404 memset(&ecmd
, 0, sizeof(ecmd
));
406 memset(&ifr
, 0, sizeof(ifr
));
407 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
409 ecmd
.cmd
= ETHTOOL_GLINK
;
410 ifr
.ifr_data
= (char *) &ecmd
;
412 ret
= ioctl(sock
, SIOCETHTOOL
, &ifr
);
422 int ethtool_drvinf(const char *ifname
, struct ethtool_drvinfo
*drvinf
)
427 sock
= af_socket(AF_INET
);
429 memset(drvinf
, 0, sizeof(*drvinf
));
431 memset(&ifr
, 0, sizeof(ifr
));
432 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
434 drvinf
->cmd
= ETHTOOL_GDRVINFO
;
435 ifr
.ifr_data
= (char *) drvinf
;
437 ret
= ioctl(sock
, SIOCETHTOOL
, &ifr
);
444 u32
device_bitrate(const char *ifname
)
446 u32 speed_c
, speed_w
;
448 speed_c
= ethtool_bitrate(ifname
);
449 speed_w
= wireless_bitrate(ifname
);
451 return (speed_c
== 0 ? speed_w
: speed_c
);
454 int device_ifindex(const char *ifname
)
456 int ret
, sock
, index
;
459 if (!strncmp("any", ifname
, strlen("any")))
462 sock
= af_socket(AF_INET
);
464 memset(&ifr
, 0, sizeof(ifr
));
465 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
467 ret
= ioctl(sock
, SIOCGIFINDEX
, &ifr
);
469 index
= ifr
.ifr_ifindex
;
478 static int __device_address6(const char *ifname
, struct sockaddr_storage
*ss
)
480 int ret
, family
, found
= -EINVAL
;
481 struct ifaddrs
*ifaddr
, *ifa
;
483 ret
= getifaddrs(&ifaddr
);
485 panic("Cannot get device addresses for IPv6!\n");
487 for (ifa
= ifaddr
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
488 family
= ifa
->ifa_addr
->sa_family
;
489 if (family
!= AF_INET6
)
491 if (strcmp(ifa
->ifa_name
, ifname
))
494 memcpy(ss
, ifa
->ifa_addr
, sizeof(*ss
));
503 int device_address(const char *ifname
, int af
, struct sockaddr_storage
*ss
)
510 if (!strncmp("any", ifname
, strlen("any")))
513 return __device_address6(ifname
, ss
);
515 sock
= af_socket(af
);
517 memset(&ifr
, 0, sizeof(ifr
));
518 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
520 ifr
.ifr_addr
.sa_family
= af
;
522 ret
= ioctl(sock
, SIOCGIFADDR
, &ifr
);
524 memcpy(ss
, &ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
531 int device_mtu(const char *ifname
)
536 sock
= af_socket(AF_INET
);
538 memset(&ifr
, 0, sizeof(ifr
));
539 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
541 ret
= ioctl(sock
, SIOCGIFMTU
, &ifr
);
552 short device_get_flags(const char *ifname
)
554 /* Really, it's short! Look at struct ifreq */
559 sock
= af_socket(AF_INET
);
561 memset(&ifr
, 0, sizeof(ifr
));
562 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
564 ret
= ioctl(sock
, SIOCGIFFLAGS
, &ifr
);
566 flags
= ifr
.ifr_flags
;
575 void device_set_flags(const char *ifname
, const short flags
)
580 sock
= af_socket(AF_INET
);
582 memset(&ifr
, 0, sizeof(ifr
));
583 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
585 ifr
.ifr_flags
= flags
;
587 ret
= ioctl(sock
, SIOCSIFFLAGS
, &ifr
);
589 panic("Cannot set NIC flags!\n");
594 /* XXX: also probe ethtool driver name if it fails */
595 int device_irq_number(const char *ifname
)
598 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
599 * supported anymore, we need to grab them from procfs
607 if (!strncmp("lo", ifname
, strlen("lo")))
610 fp
= fopen("/proc/interrupts", "r");
612 whine("Cannot open /proc/interrupts!\n");
616 memset(buff
, 0, sizeof(buff
));
617 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
618 buff
[sizeof(buff
) - 1] = 0;
620 if (strstr(buff
, ifname
) == NULL
)
624 while (*buffp
!= ':')
629 memset(buff
, 0, sizeof(buff
));
637 * Try sysfs as fallback. Probably wireless devices will be found
638 * here. We return silently if it fails ...
640 slprintf(sysname
, sizeof(sysname
), "/sys/class/net/%s/device/irq",
643 fp
= fopen(sysname
, "r");
647 memset(buff
, 0, sizeof(buff
));
648 if(fgets(buff
, sizeof(buff
), fp
) != NULL
) {
649 buff
[sizeof(buff
) - 1] = 0;
658 int device_set_irq_affinity_list(int irq
, unsigned long from
, unsigned long to
)
661 char file
[256], list
[64];
663 slprintf(file
, sizeof(file
), "/proc/irq/%d/smp_affinity_list", irq
);
664 slprintf(list
, sizeof(list
), "%lu-%lu\n", from
, to
);
666 fd
= open(file
, O_WRONLY
);
668 whine("Cannot open file %s!\n", file
);
672 ret
= write(fd
, list
, strlen(list
));
678 int device_bind_irq_to_cpu(int irq
, int cpu
)
685 /* Note: first CPU begins with CPU 0 */
686 if (irq
< 0 || cpu
< 0)
689 memset(file
, 0, sizeof(file
));
690 memset(buff
, 0, sizeof(buff
));
692 /* smp_affinity starts counting with CPU 1, 2, ... */
694 sprintf(file
, "/proc/irq/%d/smp_affinity", irq
);
696 fp
= fopen(file
, "w");
698 whine("Cannot open file %s!\n", file
);
702 sprintf(buff
, "%d", cpu
);
703 ret
= fwrite(buff
, sizeof(buff
), 1, fp
);
706 return (ret
> 0 ? 0 : ret
);
709 void sock_print_net_stats(int sock
, unsigned long skipped
)
712 struct tpacket_stats kstats
;
714 socklen_t slen
= sizeof(kstats
);
716 memset(&kstats
, 0, sizeof(kstats
));
718 ret
= getsockopt(sock
, SOL_PACKET
, PACKET_STATISTICS
, &kstats
, &slen
);
720 uint64_t packets
= kstats
.tp_packets
;
721 uint64_t drops
= kstats
.tp_drops
;
723 printf("\r%12ld packets incoming\n", packets
);
724 printf("\r%12ld packets passed filter\n",
725 packets
- drops
- skipped
);
726 printf("\r%12ld packets failed filter (out of space)\n",
728 if (kstats
.tp_packets
> 0)
729 printf("\r%12.4f%\% packet droprate\n",
730 1.f
* drops
/ packets
* 100.f
);
734 void register_signal(int signal
, void (*handler
)(int))
737 struct sigaction saction
;
739 sigfillset(&block_mask
);
741 saction
.sa_handler
= handler
;
742 saction
.sa_mask
= block_mask
;
743 saction
.sa_flags
= SA_RESTART
;
744 sigaction(signal
, &saction
, NULL
);
747 void register_signal_f(int signal
, void (*handler
)(int), int flags
)
750 struct sigaction saction
;
752 sigfillset(&block_mask
);
754 saction
.sa_handler
= handler
;
755 saction
.sa_mask
= block_mask
;
756 saction
.sa_flags
= flags
;
757 sigaction(signal
, &saction
, NULL
);
760 int get_tty_size(void)
763 struct ttysize ts
= {0};
764 return (ioctl(0, TIOCGSIZE
, &ts
) == 0 ?
765 ts
.ts_cols
: DEFAULT_TTY_SIZE
);
766 #elif defined(TIOCGWINSZ)
768 return (ioctl(0, TIOCGWINSZ
, &ts
) == 0 ?
769 ts
.ws_col
: DEFAULT_TTY_SIZE
);
771 return DEFAULT_TTY_SIZE
;
775 short enter_promiscuous_mode(char *ifname
)
779 if (!strncmp("any", ifname
, strlen("any")))
782 ifflags
= device_get_flags(ifname
);
783 device_set_flags(ifname
, ifflags
| IFF_PROMISC
);
788 void leave_promiscuous_mode(char *ifname
, short oldflags
)
790 if (!strncmp("any", ifname
, strlen("any")))
793 device_set_flags(ifname
, oldflags
);
796 int device_up(char *ifname
)
800 if (!strncmp("any", ifname
, strlen("any")))
803 return (device_get_flags(ifname
) & IFF_UP
) == IFF_UP
;
806 int device_running(char *ifname
)
810 if (!strncmp("any", ifname
, strlen("any")))
813 return (device_get_flags(ifname
) & IFF_RUNNING
) == IFF_RUNNING
;
816 int device_up_and_running(char *ifname
)
820 if (!strncmp("any", ifname
, strlen("any")))
823 return (device_get_flags(ifname
) & (IFF_UP
| IFF_RUNNING
)) ==
824 (IFF_UP
| IFF_RUNNING
);
827 int poll_error_maybe_die(int sock
, struct pollfd
*pfd
)
829 if ((pfd
->revents
& (POLLHUP
| POLLRDHUP
| POLLERR
| POLLNVAL
)) == 0)
830 return POLL_NEXT_PKT
;
831 if (pfd
->revents
& (POLLHUP
| POLLRDHUP
))
832 panic("Hangup on socket occured!\n");
833 if (pfd
->revents
& POLLERR
) {
837 if (recv(sock
, &tmp
, sizeof(tmp
), MSG_PEEK
) >= 0)
838 return POLL_NEXT_PKT
;
839 if (errno
== ENETDOWN
)
840 panic("Interface went down!\n");
842 return POLL_MOVE_OUT
;
844 if (pfd
->revents
& POLLNVAL
) {
845 whine("Invalid polling request on socket!\n");
847 return POLL_MOVE_OUT
;
850 return POLL_NEXT_PKT
;
853 static inline char *next_token(char *q
, int sep
)
858 * glibc defines this as a macro and gcc throws a false
859 * positive ``logical ‘&&’ with non-zero constant will
860 * always evaluate as true'' in older versions. See:
861 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513
868 void cpu_affinity(int cpu
)
871 cpu_set_t cpu_bitmask
;
873 CPU_ZERO(&cpu_bitmask
);
874 CPU_SET(cpu
, &cpu_bitmask
);
876 ret
= sched_setaffinity(getpid(), sizeof(cpu_bitmask
),
879 panic("Can't set this cpu affinity!\n");
882 int set_cpu_affinity(char *str
, int inverted
)
886 cpu_set_t cpu_bitmask
;
890 cpus
= get_number_cpus();
892 CPU_ZERO(&cpu_bitmask
);
894 for (i
= 0; inverted
&& i
< cpus
; ++i
)
895 CPU_SET(i
, &cpu_bitmask
);
897 while (p
= q
, q
= next_token(q
, ','), p
) {
898 unsigned int a
; /* Beginning of range */
899 unsigned int b
; /* End of range */
900 unsigned int s
; /* Stride */
903 if (sscanf(p
, "%u", &a
) < 1)
909 c1
= next_token(p
, '-');
910 c2
= next_token(p
, ',');
912 if (c1
!= NULL
&& (c2
== NULL
|| c1
< c2
)) {
913 if (sscanf(c1
, "%u", &b
) < 1)
916 c1
= next_token(c1
, ':');
918 if (c1
!= NULL
&& (c2
== NULL
|| c1
< c2
))
919 if (sscanf(c1
, "%u", &s
) < 1)
928 CPU_CLR(a
, &cpu_bitmask
);
930 CPU_SET(a
, &cpu_bitmask
);
935 ret
= sched_setaffinity(getpid(), sizeof(cpu_bitmask
),
938 panic("Can't set this cpu affinity!\n");
943 int set_proc_prio(int priority
)
946 * setpriority() is clever, even if you put a nice value which
947 * is out of range it corrects it to the closest valid nice value
949 int ret
= setpriority(PRIO_PROCESS
, getpid(), priority
);
951 panic("Can't set nice val to %i!\n", priority
);
956 int set_sched_status(int policy
, int priority
)
958 int ret
, min_prio
, max_prio
;
959 struct sched_param sp
;
961 max_prio
= sched_get_priority_max(policy
);
962 min_prio
= sched_get_priority_min(policy
);
964 if (max_prio
== -1 || min_prio
== -1)
965 whine("Cannot determine scheduler prio limits!\n");
966 else if (priority
< min_prio
)
968 else if (priority
> max_prio
)
971 memset(&sp
, 0, sizeof(sp
));
972 sp
.sched_priority
= priority
;
974 ret
= sched_setscheduler(getpid(), policy
, &sp
);
976 whine("Cannot set scheduler policy!\n");
980 ret
= sched_setparam(getpid(), &sp
);
982 whine("Cannot set scheduler prio!\n");
989 static inline int ioprio_set(int which
, int who
, int ioprio
)
991 return syscall(SYS_ioprio_set
, which
, who
, ioprio
);
994 static inline int ioprio_get(int which
, int who
)
996 return syscall(SYS_ioprio_get
, which
, who
);
999 static void ioprio_setpid(pid_t pid
, int ioprio
, int ioclass
)
1001 int ret
= ioprio_set(ioprio_who_process
, pid
,
1002 ioprio
| ioclass
<< IOPRIO_CLASS_SHIFT
);
1004 panic("Failed to set io prio for pid!\n");
1007 void ioprio_print(void)
1009 int ioprio
= ioprio_get(ioprio_who_process
, getpid());
1011 panic("Failed to fetch io prio for pid!\n");
1013 int ioclass
= ioprio
>> IOPRIO_CLASS_SHIFT
;
1014 if (ioclass
!= ioprio_class_idle
) {
1016 printf("%s: prio %d\n", to_prio
[ioclass
], ioprio
);
1018 printf("%s\n", to_prio
[ioclass
]);
1022 void set_ioprio_rt(void)
1024 ioprio_setpid(getpid(), 4, ioprio_class_rt
);
1027 void set_ioprio_be(void)
1029 ioprio_setpid(getpid(), 4, ioprio_class_be
);
1034 if (mlockall(MCL_CURRENT
| MCL_FUTURE
) != 0)
1035 panic("Cannot lock pages!\n");
1038 void xunlockme(void)
1043 int set_timeout(struct timeval
*timeval
, unsigned int msec
)
1048 timeval
->tv_sec
= 0;
1049 timeval
->tv_usec
= 0;
1052 timeval
->tv_usec
= msec
* 1000;
1056 timeval
->tv_sec
= (long) (msec
/ 1000);
1057 timeval
->tv_usec
= (long) ((msec
- (timeval
->tv_sec
* 1000)) * 1000);
1062 size_t strlcpy(char *dest
, const char *src
, size_t size
)
1064 size_t ret
= strlen(src
);
1067 size_t len
= (ret
>= size
) ? size
- 1 : ret
;
1069 memcpy(dest
, src
, len
);
1076 static inline int vslprintf(char *dst
, size_t size
, const char *fmt
, va_list ap
)
1080 ret
= vsnprintf(dst
, size
, fmt
, ap
);
1081 dst
[size
- 1] = '\0';
1086 int slprintf(char *dst
, size_t size
, const char *fmt
, ...)
1092 ret
= vslprintf(dst
, size
, fmt
, ap
);
1098 int slprintf_nocheck(char *dst
, size_t size
, const char *fmt
, ...)
1104 ret
= vslprintf(dst
, size
, fmt
, ap
);
1110 noinline
void *xmemset(void *s
, int c
, size_t n
)
1115 for (i
= 0; i
< n
; ++i
)
1116 ptr
[i
] = (uint8_t) c
;
1121 char *getuint(char *in
, uint32_t *out
)
1124 char *endptr
= NULL
;
1126 while (*in
&& (isdigit(*in
) || isxdigit(*in
) || *in
== 'x'))
1129 panic("Syntax error!\n");
1133 *out
= strtoul(pt
, &endptr
, 0);
1134 if ((endptr
!= NULL
&& *endptr
!= '\0') || errno
!= 0) {
1135 panic("Syntax error!\n");
1142 char *strtrim_right(register char *p
, register char c
)
1160 char *strtrim_left(register char *p
, register char c
)
1165 while (*p
&& len
--) {
1175 void tputchar_safe(int c
)
1177 unsigned char ch
= (unsigned char)(c
& 0xff);
1182 tprintf("\\0x%02x", ch
);
1185 void tputs_safe(const char *str
, size_t len
)
1188 tputchar_safe(*str
);