~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/net/nettest.c

Version: ~ [ linux-5.16-rc3 ] ~ [ linux-5.15.5 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.82 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.162 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.218 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.256 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.291 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.293 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* nettest - used for functional tests of networking APIs
  3  *
  4  * Copyright (c) 2013-2019 David Ahern <dsahern@gmail.com>. All rights reserved.
  5  */
  6 
  7 #define _GNU_SOURCE
  8 #include <features.h>
  9 #include <sys/types.h>
 10 #include <sys/ioctl.h>
 11 #include <sys/socket.h>
 12 #include <linux/tcp.h>
 13 #include <arpa/inet.h>
 14 #include <net/if.h>
 15 #include <netinet/in.h>
 16 #include <netdb.h>
 17 #include <fcntl.h>
 18 #include <libgen.h>
 19 #include <limits.h>
 20 #include <stdarg.h>
 21 #include <stdio.h>
 22 #include <stdlib.h>
 23 #include <string.h>
 24 #include <unistd.h>
 25 #include <time.h>
 26 #include <errno.h>
 27 
 28 #ifndef IPV6_UNICAST_IF
 29 #define IPV6_UNICAST_IF         76
 30 #endif
 31 #ifndef IPV6_MULTICAST_IF
 32 #define IPV6_MULTICAST_IF       17
 33 #endif
 34 
 35 #define DEFAULT_PORT 12345
 36 
 37 #ifndef MAX
 38 #define MAX(a, b)  ((a) > (b) ? (a) : (b))
 39 #endif
 40 #ifndef MIN
 41 #define MIN(a, b)  ((a) < (b) ? (a) : (b))
 42 #endif
 43 
 44 struct sock_args {
 45         /* local address */
 46         union {
 47                 struct in_addr  in;
 48                 struct in6_addr in6;
 49         } local_addr;
 50 
 51         /* remote address */
 52         union {
 53                 struct in_addr  in;
 54                 struct in6_addr in6;
 55         } remote_addr;
 56         int scope_id;  /* remote scope; v6 send only */
 57 
 58         struct in_addr grp;     /* multicast group */
 59 
 60         unsigned int has_local_ip:1,
 61                      has_remote_ip:1,
 62                      has_grp:1,
 63                      has_expected_laddr:1,
 64                      has_expected_raddr:1,
 65                      bind_test_only:1;
 66 
 67         unsigned short port;
 68 
 69         int type;      /* DGRAM, STREAM, RAW */
 70         int protocol;
 71         int version;   /* AF_INET/AF_INET6 */
 72 
 73         int use_setsockopt;
 74         int use_cmsg;
 75         const char *dev;
 76         int ifindex;
 77 
 78         const char *password;
 79         /* prefix for MD5 password */
 80         union {
 81                 struct sockaddr_in v4;
 82                 struct sockaddr_in6 v6;
 83         } md5_prefix;
 84         unsigned int prefix_len;
 85 
 86         /* expected addresses and device index for connection */
 87         int expected_ifindex;
 88 
 89         /* local address */
 90         union {
 91                 struct in_addr  in;
 92                 struct in6_addr in6;
 93         } expected_laddr;
 94 
 95         /* remote address */
 96         union {
 97                 struct in_addr  in;
 98                 struct in6_addr in6;
 99         } expected_raddr;
100 };
101 
102 static int server_mode;
103 static unsigned int prog_timeout = 5;
104 static unsigned int interactive;
105 static int iter = 1;
106 static char *msg = "Hello world!";
107 static int msglen;
108 static int quiet;
109 static int try_broadcast = 1;
110 
111 static char *timestamp(char *timebuf, int buflen)
112 {
113         time_t now;
114 
115         now = time(NULL);
116         if (strftime(timebuf, buflen, "%T", localtime(&now)) == 0) {
117                 memset(timebuf, 0, buflen);
118                 strncpy(timebuf, "00:00:00", buflen-1);
119         }
120 
121         return timebuf;
122 }
123 
124 static void log_msg(const char *format, ...)
125 {
126         char timebuf[64];
127         va_list args;
128 
129         if (quiet)
130                 return;
131 
132         fprintf(stdout, "%s %s:",
133                 timestamp(timebuf, sizeof(timebuf)),
134                 server_mode ? "server" : "client");
135         va_start(args, format);
136         vfprintf(stdout, format, args);
137         va_end(args);
138 
139         fflush(stdout);
140 }
141 
142 static void log_error(const char *format, ...)
143 {
144         char timebuf[64];
145         va_list args;
146 
147         if (quiet)
148                 return;
149 
150         fprintf(stderr, "%s %s:",
151                 timestamp(timebuf, sizeof(timebuf)),
152                 server_mode ? "server" : "client");
153         va_start(args, format);
154         vfprintf(stderr, format, args);
155         va_end(args);
156 
157         fflush(stderr);
158 }
159 
160 static void log_err_errno(const char *fmt, ...)
161 {
162         char timebuf[64];
163         va_list args;
164 
165         if (quiet)
166                 return;
167 
168         fprintf(stderr, "%s %s: ",
169                 timestamp(timebuf, sizeof(timebuf)),
170                 server_mode ? "server" : "client");
171         va_start(args, fmt);
172         vfprintf(stderr, fmt, args);
173         va_end(args);
174 
175         fprintf(stderr, ": %d: %s\n", errno, strerror(errno));
176         fflush(stderr);
177 }
178 
179 static void log_address(const char *desc, struct sockaddr *sa)
180 {
181         char addrstr[64];
182 
183         if (quiet)
184                 return;
185 
186         if (sa->sa_family == AF_INET) {
187                 struct sockaddr_in *s = (struct sockaddr_in *) sa;
188 
189                 log_msg("%s %s:%d",
190                         desc,
191                         inet_ntop(AF_INET, &s->sin_addr, addrstr,
192                                   sizeof(addrstr)),
193                         ntohs(s->sin_port));
194 
195         } else if (sa->sa_family == AF_INET6) {
196                 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
197 
198                 log_msg("%s [%s]:%d",
199                         desc,
200                         inet_ntop(AF_INET6, &s6->sin6_addr, addrstr,
201                                   sizeof(addrstr)),
202                         ntohs(s6->sin6_port));
203         }
204 
205         printf("\n");
206 
207         fflush(stdout);
208 }
209 
210 static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args)
211 {
212         int keylen = strlen(args->password);
213         struct tcp_md5sig md5sig = {};
214         int opt = TCP_MD5SIG;
215         int rc;
216 
217         md5sig.tcpm_keylen = keylen;
218         memcpy(md5sig.tcpm_key, args->password, keylen);
219 
220         if (args->prefix_len) {
221                 opt = TCP_MD5SIG_EXT;
222                 md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_PREFIX;
223 
224                 md5sig.tcpm_prefixlen = args->prefix_len;
225                 addr = &args->md5_prefix;
226         }
227         memcpy(&md5sig.tcpm_addr, addr, alen);
228 
229         if (args->ifindex) {
230                 opt = TCP_MD5SIG_EXT;
231                 md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_IFINDEX;
232 
233                 md5sig.tcpm_ifindex = args->ifindex;
234         }
235 
236         rc = setsockopt(sd, IPPROTO_TCP, opt, &md5sig, sizeof(md5sig));
237         if (rc < 0) {
238                 /* ENOENT is harmless. Returned when a password is cleared */
239                 if (errno == ENOENT)
240                         rc = 0;
241                 else
242                         log_err_errno("setsockopt(TCP_MD5SIG)");
243         }
244 
245         return rc;
246 }
247 
248 static int tcp_md5_remote(int sd, struct sock_args *args)
249 {
250         struct sockaddr_in sin = {
251                 .sin_family = AF_INET,
252         };
253         struct sockaddr_in6 sin6 = {
254                 .sin6_family = AF_INET6,
255         };
256         void *addr;
257         int alen;
258 
259         switch (args->version) {
260         case AF_INET:
261                 sin.sin_port = htons(args->port);
262                 sin.sin_addr = args->remote_addr.in;
263                 addr = &sin;
264                 alen = sizeof(sin);
265                 break;
266         case AF_INET6:
267                 sin6.sin6_port = htons(args->port);
268                 sin6.sin6_addr = args->remote_addr.in6;
269                 addr = &sin6;
270                 alen = sizeof(sin6);
271                 break;
272         default:
273                 log_error("unknown address family\n");
274                 exit(1);
275         }
276 
277         if (tcp_md5sig(sd, addr, alen, args))
278                 return -1;
279 
280         return 0;
281 }
282 
283 static int get_ifidx(const char *ifname)
284 {
285         struct ifreq ifdata;
286         int sd, rc;
287 
288         if (!ifname || *ifname == '\0')
289                 return -1;
290 
291         memset(&ifdata, 0, sizeof(ifdata));
292 
293         strcpy(ifdata.ifr_name, ifname);
294 
295         sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
296         if (sd < 0) {
297                 log_err_errno("socket failed");
298                 return -1;
299         }
300 
301         rc = ioctl(sd, SIOCGIFINDEX, (char *)&ifdata);
302         close(sd);
303         if (rc != 0) {
304                 log_err_errno("ioctl(SIOCGIFINDEX) failed");
305                 return -1;
306         }
307 
308         return ifdata.ifr_ifindex;
309 }
310 
311 static int bind_to_device(int sd, const char *name)
312 {
313         int rc;
314 
315         rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
316         if (rc < 0)
317                 log_err_errno("setsockopt(SO_BINDTODEVICE)");
318 
319         return rc;
320 }
321 
322 static int get_bind_to_device(int sd, char *name, size_t len)
323 {
324         int rc;
325         socklen_t optlen = len;
326 
327         name[0] = '\0';
328         rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen);
329         if (rc < 0)
330                 log_err_errno("setsockopt(SO_BINDTODEVICE)");
331 
332         return rc;
333 }
334 
335 static int check_device(int sd, struct sock_args *args)
336 {
337         int ifindex = 0;
338         char name[32];
339 
340         if (get_bind_to_device(sd, name, sizeof(name)))
341                 *name = '\0';
342         else
343                 ifindex = get_ifidx(name);
344 
345         log_msg("    bound to device %s/%d\n",
346                 *name ? name : "<none>", ifindex);
347 
348         if (!args->expected_ifindex)
349                 return 0;
350 
351         if (args->expected_ifindex != ifindex) {
352                 log_error("Device index mismatch: expected %d have %d\n",
353                           args->expected_ifindex, ifindex);
354                 return 1;
355         }
356 
357         log_msg("Device index matches: expected %d have %d\n",
358                 args->expected_ifindex, ifindex);
359 
360         return 0;
361 }
362 
363 static int set_pktinfo_v4(int sd)
364 {
365         int one = 1;
366         int rc;
367 
368         rc = setsockopt(sd, SOL_IP, IP_PKTINFO, &one, sizeof(one));
369         if (rc < 0 && rc != -ENOTSUP)
370                 log_err_errno("setsockopt(IP_PKTINFO)");
371 
372         return rc;
373 }
374 
375 static int set_recvpktinfo_v6(int sd)
376 {
377         int one = 1;
378         int rc;
379 
380         rc = setsockopt(sd, SOL_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
381         if (rc < 0 && rc != -ENOTSUP)
382                 log_err_errno("setsockopt(IPV6_RECVPKTINFO)");
383 
384         return rc;
385 }
386 
387 static int set_recverr_v4(int sd)
388 {
389         int one = 1;
390         int rc;
391 
392         rc = setsockopt(sd, SOL_IP, IP_RECVERR, &one, sizeof(one));
393         if (rc < 0 && rc != -ENOTSUP)
394                 log_err_errno("setsockopt(IP_RECVERR)");
395 
396         return rc;
397 }
398 
399 static int set_recverr_v6(int sd)
400 {
401         int one = 1;
402         int rc;
403 
404         rc = setsockopt(sd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
405         if (rc < 0 && rc != -ENOTSUP)
406                 log_err_errno("setsockopt(IPV6_RECVERR)");
407 
408         return rc;
409 }
410 
411 static int set_unicast_if(int sd, int ifindex, int version)
412 {
413         int opt = IP_UNICAST_IF;
414         int level = SOL_IP;
415         int rc;
416 
417         ifindex = htonl(ifindex);
418 
419         if (version == AF_INET6) {
420                 opt = IPV6_UNICAST_IF;
421                 level = SOL_IPV6;
422         }
423         rc = setsockopt(sd, level, opt, &ifindex, sizeof(ifindex));
424         if (rc < 0)
425                 log_err_errno("setsockopt(IP_UNICAST_IF)");
426 
427         return rc;
428 }
429 
430 static int set_multicast_if(int sd, int ifindex)
431 {
432         struct ip_mreqn mreq = { .imr_ifindex = ifindex };
433         int rc;
434 
435         rc = setsockopt(sd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq));
436         if (rc < 0)
437                 log_err_errno("setsockopt(IP_MULTICAST_IF)");
438 
439         return rc;
440 }
441 
442 static int set_membership(int sd, uint32_t grp, uint32_t addr, int ifindex)
443 {
444         uint32_t if_addr = addr;
445         struct ip_mreqn mreq;
446         int rc;
447 
448         if (addr == htonl(INADDR_ANY) && !ifindex) {
449                 log_error("Either local address or device needs to be given for multicast membership\n");
450                 return -1;
451         }
452 
453         mreq.imr_multiaddr.s_addr = grp;
454         mreq.imr_address.s_addr = if_addr;
455         mreq.imr_ifindex = ifindex;
456 
457         rc = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
458         if (rc < 0) {
459                 log_err_errno("setsockopt(IP_ADD_MEMBERSHIP)");
460                 return -1;
461         }
462 
463         return 0;
464 }
465 
466 static int set_broadcast(int sd)
467 {
468         unsigned int one = 1;
469         int rc = 0;
470 
471         if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) != 0) {
472                 log_err_errno("setsockopt(SO_BROADCAST)");
473                 rc = -1;
474         }
475 
476         return rc;
477 }
478 
479 static int set_reuseport(int sd)
480 {
481         unsigned int one = 1;
482         int rc = 0;
483 
484         if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) != 0) {
485                 log_err_errno("setsockopt(SO_REUSEPORT)");
486                 rc = -1;
487         }
488 
489         return rc;
490 }
491 
492 static int set_reuseaddr(int sd)
493 {
494         unsigned int one = 1;
495         int rc = 0;
496 
497         if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != 0) {
498                 log_err_errno("setsockopt(SO_REUSEADDR)");
499                 rc = -1;
500         }
501 
502         return rc;
503 }
504 
505 static int str_to_uint(const char *str, int min, int max, unsigned int *value)
506 {
507         int number;
508         char *end;
509 
510         errno = 0;
511         number = (unsigned int) strtoul(str, &end, 0);
512 
513         /* entire string should be consumed by conversion
514          * and value should be between min and max
515          */
516         if (((*end == '\0') || (*end == '\n')) && (end != str) &&
517             (errno != ERANGE) && (min <= number) && (number <= max)) {
518                 *value = number;
519                 return 0;
520         }
521 
522         return -1;
523 }
524 
525 static int expected_addr_match(struct sockaddr *sa, void *expected,
526                                const char *desc)
527 {
528         char addrstr[64];
529         int rc = 0;
530 
531         if (sa->sa_family == AF_INET) {
532                 struct sockaddr_in *s = (struct sockaddr_in *) sa;
533                 struct in_addr *exp_in = (struct in_addr *) expected;
534 
535                 if (s->sin_addr.s_addr != exp_in->s_addr) {
536                         log_error("%s address does not match expected %s",
537                                   desc,
538                                   inet_ntop(AF_INET, exp_in,
539                                             addrstr, sizeof(addrstr)));
540                         rc = 1;
541                 }
542         } else if (sa->sa_family == AF_INET6) {
543                 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
544                 struct in6_addr *exp_in = (struct in6_addr *) expected;
545 
546                 if (memcmp(&s6->sin6_addr, exp_in, sizeof(*exp_in))) {
547                         log_error("%s address does not match expected %s",
548                                   desc,
549                                   inet_ntop(AF_INET6, exp_in,
550                                             addrstr, sizeof(addrstr)));
551                         rc = 1;
552                 }
553         } else {
554                 log_error("%s address does not match expected - unknown family",
555                           desc);
556                 rc = 1;
557         }
558 
559         if (!rc)
560                 log_msg("%s address matches expected\n", desc);
561 
562         return rc;
563 }
564 
565 static int show_sockstat(int sd, struct sock_args *args)
566 {
567         struct sockaddr_in6 local_addr, remote_addr;
568         socklen_t alen = sizeof(local_addr);
569         struct sockaddr *sa;
570         const char *desc;
571         int rc = 0;
572 
573         desc = server_mode ? "server local:" : "client local:";
574         sa = (struct sockaddr *) &local_addr;
575         if (getsockname(sd, sa, &alen) == 0) {
576                 log_address(desc, sa);
577 
578                 if (args->has_expected_laddr) {
579                         rc = expected_addr_match(sa, &args->expected_laddr,
580                                                  "local");
581                 }
582         } else {
583                 log_err_errno("getsockname failed");
584         }
585 
586         sa = (struct sockaddr *) &remote_addr;
587         desc = server_mode ? "server peer:" : "client peer:";
588         if (getpeername(sd, sa, &alen) == 0) {
589                 log_address(desc, sa);
590 
591                 if (args->has_expected_raddr) {
592                         rc |= expected_addr_match(sa, &args->expected_raddr,
593                                                  "remote");
594                 }
595         } else {
596                 log_err_errno("getpeername failed");
597         }
598 
599         return rc;
600 }
601 
602 static int get_index_from_cmsg(struct msghdr *m)
603 {
604         struct cmsghdr *cm;
605         int ifindex = 0;
606         char buf[64];
607 
608         for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(m);
609              m->msg_controllen != 0 && cm;
610              cm = (struct cmsghdr *)CMSG_NXTHDR(m, cm)) {
611 
612                 if (cm->cmsg_level == SOL_IP &&
613                     cm->cmsg_type == IP_PKTINFO) {
614                         struct in_pktinfo *pi;
615 
616                         pi = (struct in_pktinfo *)(CMSG_DATA(cm));
617                         inet_ntop(AF_INET, &pi->ipi_addr, buf, sizeof(buf));
618                         ifindex = pi->ipi_ifindex;
619                 } else if (cm->cmsg_level == SOL_IPV6 &&
620                            cm->cmsg_type == IPV6_PKTINFO) {
621                         struct in6_pktinfo *pi6;
622 
623                         pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm));
624                         inet_ntop(AF_INET6, &pi6->ipi6_addr, buf, sizeof(buf));
625                         ifindex = pi6->ipi6_ifindex;
626                 }
627         }
628 
629         if (ifindex) {
630                 log_msg("    pktinfo: ifindex %d dest addr %s\n",
631                         ifindex, buf);
632         }
633         return ifindex;
634 }
635 
636 static int send_msg_no_cmsg(int sd, void *addr, socklen_t alen)
637 {
638         int err;
639 
640 again:
641         err = sendto(sd, msg, msglen, 0, addr, alen);
642         if (err < 0) {
643                 if (errno == EACCES && try_broadcast) {
644                         try_broadcast = 0;
645                         if (!set_broadcast(sd))
646                                 goto again;
647                         errno = EACCES;
648                 }
649 
650                 log_err_errno("sendto failed");
651                 return 1;
652         }
653 
654         return 0;
655 }
656 
657 static int send_msg_cmsg(int sd, void *addr, socklen_t alen,
658                          int ifindex, int version)
659 {
660         unsigned char cmsgbuf[64];
661         struct iovec iov[2];
662         struct cmsghdr *cm;
663         struct msghdr m;
664         int err;
665 
666         iov[0].iov_base = msg;
667         iov[0].iov_len = msglen;
668         m.msg_iov = iov;
669         m.msg_iovlen = 1;
670         m.msg_name = (caddr_t)addr;
671         m.msg_namelen = alen;
672 
673         memset(cmsgbuf, 0, sizeof(cmsgbuf));
674         cm = (struct cmsghdr *)cmsgbuf;
675         m.msg_control = (caddr_t)cm;
676 
677         if (version == AF_INET) {
678                 struct in_pktinfo *pi;
679 
680                 cm->cmsg_level = SOL_IP;
681                 cm->cmsg_type = IP_PKTINFO;
682                 cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
683                 pi = (struct in_pktinfo *)(CMSG_DATA(cm));
684                 pi->ipi_ifindex = ifindex;
685 
686                 m.msg_controllen = cm->cmsg_len;
687 
688         } else if (version == AF_INET6) {
689                 struct in6_pktinfo *pi6;
690 
691                 cm->cmsg_level = SOL_IPV6;
692                 cm->cmsg_type = IPV6_PKTINFO;
693                 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
694 
695                 pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm));
696                 pi6->ipi6_ifindex = ifindex;
697 
698                 m.msg_controllen = cm->cmsg_len;
699         }
700 
701 again:
702         err = sendmsg(sd, &m, 0);
703         if (err < 0) {
704                 if (errno == EACCES && try_broadcast) {
705                         try_broadcast = 0;
706                         if (!set_broadcast(sd))
707                                 goto again;
708                         errno = EACCES;
709                 }
710 
711                 log_err_errno("sendmsg failed");
712                 return 1;
713         }
714 
715         return 0;
716 }
717 
718 
719 static int send_msg(int sd, void *addr, socklen_t alen, struct sock_args *args)
720 {
721         if (args->type == SOCK_STREAM) {
722                 if (write(sd, msg, msglen) < 0) {
723                         log_err_errno("write failed sending msg to peer");
724                         return 1;
725                 }
726         } else if (args->ifindex && args->use_cmsg) {
727                 if (send_msg_cmsg(sd, addr, alen, args->ifindex, args->version))
728                         return 1;
729         } else {
730                 if (send_msg_no_cmsg(sd, addr, alen))
731                         return 1;
732         }
733 
734         log_msg("Sent message:\n");
735         log_msg("    %.24s%s\n", msg, msglen > 24 ? " ..." : "");
736 
737         return 0;
738 }
739 
740 static int socket_read_dgram(int sd, struct sock_args *args)
741 {
742         unsigned char addr[sizeof(struct sockaddr_in6)];
743         struct sockaddr *sa = (struct sockaddr *) addr;
744         socklen_t alen = sizeof(addr);
745         struct iovec iov[2];
746         struct msghdr m = {
747                 .msg_name = (caddr_t)addr,
748                 .msg_namelen = alen,
749                 .msg_iov = iov,
750                 .msg_iovlen = 1,
751         };
752         unsigned char cmsgbuf[256];
753         struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf;
754         char buf[16*1024];
755         int ifindex;
756         int len;
757 
758         iov[0].iov_base = (caddr_t)buf;
759         iov[0].iov_len = sizeof(buf);
760 
761         memset(cmsgbuf, 0, sizeof(cmsgbuf));
762         m.msg_control = (caddr_t)cm;
763         m.msg_controllen = sizeof(cmsgbuf);
764 
765         len = recvmsg(sd, &m, 0);
766         if (len == 0) {
767                 log_msg("peer closed connection.\n");
768                 return 0;
769         } else if (len < 0) {
770                 log_msg("failed to read message: %d: %s\n",
771                         errno, strerror(errno));
772                 return -1;
773         }
774 
775         buf[len] = '\0';
776 
777         log_address("Message from:", sa);
778         log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");
779 
780         ifindex = get_index_from_cmsg(&m);
781         if (args->expected_ifindex) {
782                 if (args->expected_ifindex != ifindex) {
783                         log_error("Device index mismatch: expected %d have %d\n",
784                                   args->expected_ifindex, ifindex);
785                         return -1;
786                 }
787                 log_msg("Device index matches: expected %d have %d\n",
788                         args->expected_ifindex, ifindex);
789         }
790 
791         if (!interactive && server_mode) {
792                 if (sa->sa_family == AF_INET6) {
793                         struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
794                         struct in6_addr *in6 = &s6->sin6_addr;
795 
796                         if (IN6_IS_ADDR_V4MAPPED(in6)) {
797                                 const uint32_t *pa = (uint32_t *) &in6->s6_addr;
798                                 struct in_addr in4;
799                                 struct sockaddr_in *sin;
800 
801                                 sin = (struct sockaddr_in *) addr;
802                                 pa += 3;
803                                 in4.s_addr = *pa;
804                                 sin->sin_addr = in4;
805                                 sin->sin_family = AF_INET;
806                                 if (send_msg_cmsg(sd, addr, alen,
807                                                   ifindex, AF_INET) < 0)
808                                         goto out_err;
809                         }
810                 }
811 again:
812                 iov[0].iov_len = len;
813 
814                 if (args->version == AF_INET6) {
815                         struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
816 
817                         if (args->dev) {
818                                 /* avoid PKTINFO conflicts with bindtodev */
819                                 if (sendto(sd, buf, len, 0,
820                                            (void *) addr, alen) < 0)
821                                         goto out_err;
822                         } else {
823                                 /* kernel is allowing scope_id to be set to VRF
824                                  * index for LLA. for sends to global address
825                                  * reset scope id
826                                  */
827                                 s6->sin6_scope_id = ifindex;
828                                 if (sendmsg(sd, &m, 0) < 0)
829                                         goto out_err;
830                         }
831                 } else {
832                         int err;
833 
834                         err = sendmsg(sd, &m, 0);
835                         if (err < 0) {
836                                 if (errno == EACCES && try_broadcast) {
837                                         try_broadcast = 0;
838                                         if (!set_broadcast(sd))
839                                                 goto again;
840                                         errno = EACCES;
841                                 }
842                                 goto out_err;
843                         }
844                 }
845                 log_msg("Sent message:\n");
846                 log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");
847         }
848 
849         return 1;
850 out_err:
851         log_err_errno("failed to send msg to peer");
852         return -1;
853 }
854 
855 static int socket_read_stream(int sd)
856 {
857         char buf[1024];
858         int len;
859 
860         len = read(sd, buf, sizeof(buf)-1);
861         if (len == 0) {
862                 log_msg("client closed connection.\n");
863                 return 0;
864         } else if (len < 0) {
865                 log_msg("failed to read message\n");
866                 return -1;
867         }
868 
869         buf[len] = '\0';
870         log_msg("Incoming message:\n");
871         log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");
872 
873         if (!interactive && server_mode) {
874                 if (write(sd, buf, len) < 0) {
875                         log_err_errno("failed to send buf");
876                         return -1;
877                 }
878                 log_msg("Sent message:\n");
879                 log_msg("     %.24s%s\n", buf, len > 24 ? " ..." : "");
880         }
881 
882         return 1;
883 }
884 
885 static int socket_read(int sd, struct sock_args *args)
886 {
887         if (args->type == SOCK_STREAM)
888                 return socket_read_stream(sd);
889 
890         return socket_read_dgram(sd, args);
891 }
892 
893 static int stdin_to_socket(int sd, int type, void *addr, socklen_t alen)
894 {
895         char buf[1024];
896         int len;
897 
898         if (fgets(buf, sizeof(buf), stdin) == NULL)
899                 return 0;
900 
901         len = strlen(buf);
902         if (type == SOCK_STREAM) {
903                 if (write(sd, buf, len) < 0) {
904                         log_err_errno("failed to send buf");
905                         return -1;
906                 }
907         } else {
908                 int err;
909 
910 again:
911                 err = sendto(sd, buf, len, 0, addr, alen);
912                 if (err < 0) {
913                         if (errno == EACCES && try_broadcast) {
914                                 try_broadcast = 0;
915                                 if (!set_broadcast(sd))
916                                         goto again;
917                                 errno = EACCES;
918                         }
919                         log_err_errno("failed to send msg to peer");
920                         return -1;
921                 }
922         }
923         log_msg("Sent message:\n");
924         log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");
925 
926         return 1;
927 }
928 
929 static void set_recv_attr(int sd, int version)
930 {
931         if (version == AF_INET6) {
932                 set_recvpktinfo_v6(sd);
933                 set_recverr_v6(sd);
934         } else {
935                 set_pktinfo_v4(sd);
936                 set_recverr_v4(sd);
937         }
938 }
939 
940 static int msg_loop(int client, int sd, void *addr, socklen_t alen,
941                     struct sock_args *args)
942 {
943         struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL;
944         fd_set rfds;
945         int nfds;
946         int rc;
947 
948         if (args->type != SOCK_STREAM)
949                 set_recv_attr(sd, args->version);
950 
951         if (msg) {
952                 msglen = strlen(msg);
953 
954                 /* client sends first message */
955                 if (client) {
956                         if (send_msg(sd, addr, alen, args))
957                                 return 1;
958                 }
959                 if (!interactive) {
960                         ptval = &timeout;
961                         if (!prog_timeout)
962                                 timeout.tv_sec = 5;
963                 }
964         }
965 
966         nfds = interactive ? MAX(fileno(stdin), sd)  + 1 : sd + 1;
967         while (1) {
968                 FD_ZERO(&rfds);
969                 FD_SET(sd, &rfds);
970                 if (interactive)
971                         FD_SET(fileno(stdin), &rfds);
972 
973                 rc = select(nfds, &rfds, NULL, NULL, ptval);
974                 if (rc < 0) {
975                         if (errno == EINTR)
976                                 continue;
977 
978                         rc = 1;
979                         log_err_errno("select failed");
980                         break;
981                 } else if (rc == 0) {
982                         log_error("Timed out waiting for response\n");
983                         rc = 2;
984                         break;
985                 }
986 
987                 if (FD_ISSET(sd, &rfds)) {
988                         rc = socket_read(sd, args);
989                         if (rc < 0) {
990                                 rc = 1;
991                                 break;
992                         }
993                         if (rc == 0)
994                                 break;
995                 }
996 
997                 rc = 0;
998 
999                 if (FD_ISSET(fileno(stdin), &rfds)) {
1000                         if (stdin_to_socket(sd, args->type, addr, alen) <= 0)
1001                                 break;
1002                 }
1003 
1004                 if (interactive)
1005                         continue;
1006 
1007                 if (iter != -1) {
1008                         --iter;
1009                         if (iter == 0)
1010                                 break;
1011                 }
1012 
1013                 log_msg("Going into quiet mode\n");
1014                 quiet = 1;
1015 
1016                 if (client) {
1017                         if (send_msg(sd, addr, alen, args)) {
1018                                 rc = 1;
1019                                 break;
1020                         }
1021                 }
1022         }
1023 
1024         return rc;
1025 }
1026 
1027 static int msock_init(struct sock_args *args, int server)
1028 {
1029         uint32_t if_addr = htonl(INADDR_ANY);
1030         struct sockaddr_in laddr = {
1031                 .sin_family = AF_INET,
1032                 .sin_port = htons(args->port),
1033         };
1034         int one = 1;
1035         int sd;
1036 
1037         if (!server && args->has_local_ip)
1038                 if_addr = args->local_addr.in.s_addr;
1039 
1040         sd = socket(PF_INET, SOCK_DGRAM, 0);
1041         if (sd < 0) {
1042                 log_err_errno("socket");
1043                 return -1;
1044         }
1045 
1046         if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
1047                        (char *)&one, sizeof(one)) < 0) {
1048                 log_err_errno("Setting SO_REUSEADDR error");
1049                 goto out_err;
1050         }
1051 
1052         if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST,
1053                        (char *)&one, sizeof(one)) < 0)
1054                 log_err_errno("Setting SO_BROADCAST error");
1055 
1056         if (args->dev && bind_to_device(sd, args->dev) != 0)
1057                 goto out_err;
1058         else if (args->use_setsockopt &&
1059                  set_multicast_if(sd, args->ifindex))
1060                 goto out_err;
1061 
1062         laddr.sin_addr.s_addr = if_addr;
1063 
1064         if (bind(sd, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {
1065                 log_err_errno("bind failed");
1066                 goto out_err;
1067         }
1068 
1069         if (server &&
1070             set_membership(sd, args->grp.s_addr,
1071                            args->local_addr.in.s_addr, args->ifindex))
1072                 goto out_err;
1073 
1074         return sd;
1075 out_err:
1076         close(sd);
1077         return -1;
1078 }
1079 
1080 static int msock_server(struct sock_args *args)
1081 {
1082         return msock_init(args, 1);
1083 }
1084 
1085 static int msock_client(struct sock_args *args)
1086 {
1087         return msock_init(args, 0);
1088 }
1089 
1090 static int bind_socket(int sd, struct sock_args *args)
1091 {
1092         struct sockaddr_in serv_addr = {
1093                 .sin_family = AF_INET,
1094         };
1095         struct sockaddr_in6 serv6_addr = {
1096                 .sin6_family = AF_INET6,
1097         };
1098         void *addr;
1099         socklen_t alen;
1100 
1101         if (!args->has_local_ip && args->type == SOCK_RAW)
1102                 return 0;
1103 
1104         switch (args->version) {
1105         case AF_INET:
1106                 serv_addr.sin_port = htons(args->port);
1107                 serv_addr.sin_addr = args->local_addr.in;
1108                 addr = &serv_addr;
1109                 alen = sizeof(serv_addr);
1110                 break;
1111 
1112         case AF_INET6:
1113                 serv6_addr.sin6_port = htons(args->port);
1114                 serv6_addr.sin6_addr = args->local_addr.in6;
1115                 addr = &serv6_addr;
1116                 alen = sizeof(serv6_addr);
1117                 break;
1118 
1119         default:
1120                 log_error("Invalid address family\n");
1121                 return -1;
1122         }
1123 
1124         if (bind(sd, addr, alen) < 0) {
1125                 log_err_errno("error binding socket");
1126                 return -1;
1127         }
1128 
1129         return 0;
1130 }
1131 
1132 static int lsock_init(struct sock_args *args)
1133 {
1134         long flags;
1135         int sd;
1136 
1137         sd = socket(args->version, args->type, args->protocol);
1138         if (sd < 0) {
1139                 log_err_errno("Error opening socket");
1140                 return  -1;
1141         }
1142 
1143         if (set_reuseaddr(sd) != 0)
1144                 goto err;
1145 
1146         if (set_reuseport(sd) != 0)
1147                 goto err;
1148 
1149         if (args->dev && bind_to_device(sd, args->dev) != 0)
1150                 goto err;
1151         else if (args->use_setsockopt &&
1152                  set_unicast_if(sd, args->ifindex, args->version))
1153                 goto err;
1154 
1155         if (bind_socket(sd, args))
1156                 goto err;
1157 
1158         if (args->bind_test_only)
1159                 goto out;
1160 
1161         if (args->type == SOCK_STREAM && listen(sd, 1) < 0) {
1162                 log_err_errno("listen failed");
1163                 goto err;
1164         }
1165 
1166         flags = fcntl(sd, F_GETFL);
1167         if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) {
1168                 log_err_errno("Failed to set non-blocking option");
1169                 goto err;
1170         }
1171 
1172         if (fcntl(sd, F_SETFD, FD_CLOEXEC) < 0)
1173                 log_err_errno("Failed to set close-on-exec flag");
1174 
1175 out:
1176         return sd;
1177 
1178 err:
1179         close(sd);
1180         return -1;
1181 }
1182 
1183 static int do_server(struct sock_args *args)
1184 {
1185         struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL;
1186         unsigned char addr[sizeof(struct sockaddr_in6)] = {};
1187         socklen_t alen = sizeof(addr);
1188         int lsd, csd = -1;
1189 
1190         fd_set rfds;
1191         int rc;
1192 
1193         if (prog_timeout)
1194                 ptval = &timeout;
1195 
1196         if (args->has_grp)
1197                 lsd = msock_server(args);
1198         else
1199                 lsd = lsock_init(args);
1200 
1201         if (lsd < 0)
1202                 return 1;
1203 
1204         if (args->bind_test_only) {
1205                 close(lsd);
1206                 return 0;
1207         }
1208 
1209         if (args->type != SOCK_STREAM) {
1210                 rc = msg_loop(0, lsd, (void *) addr, alen, args);
1211                 close(lsd);
1212                 return rc;
1213         }
1214 
1215         if (args->password && tcp_md5_remote(lsd, args)) {
1216                 close(lsd);
1217                 return 1;
1218         }
1219 
1220         while (1) {
1221                 log_msg("\n");
1222                 log_msg("waiting for client connection.\n");
1223                 FD_ZERO(&rfds);
1224                 FD_SET(lsd, &rfds);
1225 
1226                 rc = select(lsd+1, &rfds, NULL, NULL, ptval);
1227                 if (rc == 0) {
1228                         rc = 2;
1229                         break;
1230                 }
1231 
1232                 if (rc < 0) {
1233                         if (errno == EINTR)
1234                                 continue;
1235 
1236                         log_err_errno("select failed");
1237                         break;
1238                 }
1239 
1240                 if (FD_ISSET(lsd, &rfds)) {
1241 
1242                         csd = accept(lsd, (void *) addr, &alen);
1243                         if (csd < 0) {
1244                                 log_err_errno("accept failed");
1245                                 break;
1246                         }
1247 
1248                         rc = show_sockstat(csd, args);
1249                         if (rc)
1250                                 break;
1251 
1252                         rc = check_device(csd, args);
1253                         if (rc)
1254                                 break;
1255                 }
1256 
1257                 rc = msg_loop(0, csd, (void *) addr, alen, args);
1258                 close(csd);
1259 
1260                 if (!interactive)
1261                         break;
1262         }
1263 
1264         close(lsd);
1265 
1266         return rc;
1267 }
1268 
1269 static int wait_for_connect(int sd)
1270 {
1271         struct timeval _tv = { .tv_sec = prog_timeout }, *tv = NULL;
1272         fd_set wfd;
1273         int val = 0, sz = sizeof(val);
1274         int rc;
1275 
1276         FD_ZERO(&wfd);
1277         FD_SET(sd, &wfd);
1278 
1279         if (prog_timeout)
1280                 tv = &_tv;
1281 
1282         rc = select(FD_SETSIZE, NULL, &wfd, NULL, tv);
1283         if (rc == 0) {
1284                 log_error("connect timed out\n");
1285                 return -2;
1286         } else if (rc < 0) {
1287                 log_err_errno("select failed");
1288                 return -3;
1289         }
1290 
1291         if (getsockopt(sd, SOL_SOCKET, SO_ERROR, &val, (socklen_t *)&sz) < 0) {
1292                 log_err_errno("getsockopt(SO_ERROR) failed");
1293                 return -4;
1294         }
1295 
1296         if (val != 0) {
1297                 log_error("connect failed: %d: %s\n", val, strerror(val));
1298                 return -1;
1299         }
1300 
1301         return 0;
1302 }
1303 
1304 static int connectsock(void *addr, socklen_t alen, struct sock_args *args)
1305 {
1306         int sd, rc = -1;
1307         long flags;
1308 
1309         sd = socket(args->version, args->type, args->protocol);
1310         if (sd < 0) {
1311                 log_err_errno("Failed to create socket");
1312                 return -1;
1313         }
1314 
1315         flags = fcntl(sd, F_GETFL);
1316         if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) {
1317                 log_err_errno("Failed to set non-blocking option");
1318                 goto err;
1319         }
1320 
1321         if (set_reuseport(sd) != 0)
1322                 goto err;
1323 
1324         if (args->dev && bind_to_device(sd, args->dev) != 0)
1325                 goto err;
1326         else if (args->use_setsockopt &&
1327                  set_unicast_if(sd, args->ifindex, args->version))
1328                 goto err;
1329 
1330         if (args->has_local_ip && bind_socket(sd, args))
1331                 goto err;
1332 
1333         if (args->type != SOCK_STREAM)
1334                 goto out;
1335 
1336         if (args->password && tcp_md5sig(sd, addr, alen, args))
1337                 goto err;
1338 
1339         if (args->bind_test_only)
1340                 goto out;
1341 
1342         if (connect(sd, addr, alen) < 0) {
1343                 if (errno != EINPROGRESS) {
1344                         log_err_errno("Failed to connect to remote host");
1345                         rc = -1;
1346                         goto err;
1347                 }
1348                 rc = wait_for_connect(sd);
1349                 if (rc < 0)
1350                         goto err;
1351         }
1352 out:
1353         return sd;
1354 
1355 err:
1356         close(sd);
1357         return rc;
1358 }
1359 
1360 static int do_client(struct sock_args *args)
1361 {
1362         struct sockaddr_in sin = {
1363                 .sin_family = AF_INET,
1364         };
1365         struct sockaddr_in6 sin6 = {
1366                 .sin6_family = AF_INET6,
1367         };
1368         void *addr;
1369         int alen;
1370         int rc = 0;
1371         int sd;
1372 
1373         if (!args->has_remote_ip && !args->has_grp) {
1374                 fprintf(stderr, "remote IP or multicast group not given\n");
1375                 return 1;
1376         }
1377 
1378         switch (args->version) {
1379         case AF_INET:
1380                 sin.sin_port = htons(args->port);
1381                 if (args->has_grp)
1382                         sin.sin_addr = args->grp;
1383                 else
1384                         sin.sin_addr = args->remote_addr.in;
1385                 addr = &sin;
1386                 alen = sizeof(sin);
1387                 break;
1388         case AF_INET6:
1389                 sin6.sin6_port = htons(args->port);
1390                 sin6.sin6_addr = args->remote_addr.in6;
1391                 sin6.sin6_scope_id = args->scope_id;
1392                 addr = &sin6;
1393                 alen = sizeof(sin6);
1394                 break;
1395         }
1396 
1397         if (args->has_grp)
1398                 sd = msock_client(args);
1399         else
1400                 sd = connectsock(addr, alen, args);
1401 
1402         if (sd < 0)
1403                 return -sd;
1404 
1405         if (args->bind_test_only)
1406                 goto out;
1407 
1408         if (args->type == SOCK_STREAM) {
1409                 rc = show_sockstat(sd, args);
1410                 if (rc != 0)
1411                         goto out;
1412         }
1413 
1414         rc = msg_loop(1, sd, addr, alen, args);
1415 
1416 out:
1417         close(sd);
1418 
1419         return rc;
1420 }
1421 
1422 enum addr_type {
1423         ADDR_TYPE_LOCAL,
1424         ADDR_TYPE_REMOTE,
1425         ADDR_TYPE_MCAST,
1426         ADDR_TYPE_EXPECTED_LOCAL,
1427         ADDR_TYPE_EXPECTED_REMOTE,
1428         ADDR_TYPE_MD5_PREFIX,
1429 };
1430 
1431 static int convert_addr(struct sock_args *args, const char *_str,
1432                         enum addr_type atype)
1433 {
1434         int pfx_len_max = args->version == AF_INET6 ? 128 : 32;
1435         int family = args->version;
1436         char *str, *dev, *sep;
1437         struct in6_addr *in6;
1438         struct in_addr  *in;
1439         const char *desc;
1440         void *addr;
1441         int rc = 0;
1442 
1443         str = strdup(_str);
1444         if (!str)
1445                 return -ENOMEM;
1446 
1447         switch (atype) {
1448         case ADDR_TYPE_LOCAL:
1449                 desc = "local";
1450                 addr = &args->local_addr;
1451                 break;
1452         case ADDR_TYPE_REMOTE:
1453                 desc = "remote";
1454                 addr = &args->remote_addr;
1455                 break;
1456         case ADDR_TYPE_MCAST:
1457                 desc = "mcast grp";
1458                 addr = &args->grp;
1459                 break;
1460         case ADDR_TYPE_EXPECTED_LOCAL:
1461                 desc = "expected local";
1462                 addr = &args->expected_laddr;
1463                 break;
1464         case ADDR_TYPE_EXPECTED_REMOTE:
1465                 desc = "expected remote";
1466                 addr = &args->expected_raddr;
1467                 break;
1468         case ADDR_TYPE_MD5_PREFIX:
1469                 desc = "md5 prefix";
1470                 if (family == AF_INET) {
1471                         args->md5_prefix.v4.sin_family = AF_INET;
1472                         addr = &args->md5_prefix.v4.sin_addr;
1473                 } else if (family == AF_INET6) {
1474                         args->md5_prefix.v6.sin6_family = AF_INET6;
1475                         addr = &args->md5_prefix.v6.sin6_addr;
1476                 } else
1477                         return 1;
1478 
1479                 sep = strchr(str, '/');
1480                 if (sep) {
1481                         *sep = '\0';
1482                         sep++;
1483                         if (str_to_uint(sep, 1, pfx_len_max,
1484                                         &args->prefix_len) != 0) {
1485                                 fprintf(stderr, "Invalid port\n");
1486                                 return 1;
1487                         }
1488                 } else {
1489                         args->prefix_len = pfx_len_max;
1490                 }
1491                 break;
1492         default:
1493                 log_error("unknown address type");
1494                 exit(1);
1495         }
1496 
1497         switch (family) {
1498         case AF_INET:
1499                 in  = (struct in_addr *) addr;
1500                 if (str) {
1501                         if (inet_pton(AF_INET, str, in) == 0) {
1502                                 log_error("Invalid %s IP address\n", desc);
1503                                 rc = -1;
1504                                 goto out;
1505                         }
1506                 } else {
1507                         in->s_addr = htonl(INADDR_ANY);
1508                 }
1509                 break;
1510 
1511         case AF_INET6:
1512                 dev = strchr(str, '%');
1513                 if (dev) {
1514                         *dev = '\0';
1515                         dev++;
1516                 }
1517 
1518                 in6 = (struct in6_addr *) addr;
1519                 if (str) {
1520                         if (inet_pton(AF_INET6, str, in6) == 0) {
1521                                 log_error("Invalid %s IPv6 address\n", desc);
1522                                 rc = -1;
1523                                 goto out;
1524                         }
1525                 } else {
1526                         *in6 = in6addr_any;
1527                 }
1528                 if (dev) {
1529                         args->scope_id = get_ifidx(dev);
1530                         if (args->scope_id < 0) {
1531                                 log_error("Invalid scope on %s IPv6 address\n",
1532                                           desc);
1533                                 rc = -1;
1534                                 goto out;
1535                         }
1536                 }
1537                 break;
1538 
1539         default:
1540                 log_error("Invalid address family\n");
1541         }
1542 
1543 out:
1544         free(str);
1545         return rc;
1546 }
1547 
1548 static char *random_msg(int len)
1549 {
1550         int i, n = 0, olen = len + 1;
1551         char *m;
1552 
1553         if (len <= 0)
1554                 return NULL;
1555 
1556         m = malloc(olen);
1557         if (!m)
1558                 return NULL;
1559 
1560         while (len > 26) {
1561                 i = snprintf(m + n, olen - n, "%.26s",
1562                              "abcdefghijklmnopqrstuvwxyz");
1563                 n += i;
1564                 len -= i;
1565         }
1566         i = snprintf(m + n, olen - n, "%.*s", len,
1567                      "abcdefghijklmnopqrstuvwxyz");
1568         return m;
1569 }
1570 
1571 #define GETOPT_STR  "sr:l:p:t:g:P:DRn:M:m:d:SCi6L:0:1:2:Fbq"
1572 
1573 static void print_usage(char *prog)
1574 {
1575         printf(
1576         "usage: %s OPTS\n"
1577         "Required:\n"
1578         "    -r addr       remote address to connect to (client mode only)\n"
1579         "    -p port       port to connect to (client mode)/listen on (server mode)\n"
1580         "                  (default: %d)\n"
1581         "    -s            server mode (default: client mode)\n"
1582         "    -t            timeout seconds (default: none)\n"
1583         "\n"
1584         "Optional:\n"
1585         "    -F            Restart server loop\n"
1586         "    -6            IPv6 (default is IPv4)\n"
1587         "    -P proto      protocol for socket: icmp, ospf (default: none)\n"
1588         "    -D|R          datagram (D) / raw (R) socket (default stream)\n"
1589         "    -l addr       local address to bind to\n"
1590         "\n"
1591         "    -d dev        bind socket to given device name\n"
1592         "    -S            use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n"
1593         "                  to set device binding\n"
1594         "    -C            use cmsg and IP_PKTINFO to specify device binding\n"
1595         "\n"
1596         "    -L len        send random message of given length\n"
1597         "    -n num        number of times to send message\n"
1598         "\n"
1599         "    -M password   use MD5 sum protection\n"
1600         "    -m prefix/len prefix and length to use for MD5 key\n"
1601         "    -g grp        multicast group (e.g., 239.1.1.1)\n"
1602         "    -i            interactive mode (default is echo and terminate)\n"
1603         "\n"
1604         "    -0 addr       Expected local address\n"
1605         "    -1 addr       Expected remote address\n"
1606         "    -2 dev        Expected device name (or index) to receive packet\n"
1607         "\n"
1608         "    -b            Bind test only.\n"
1609         "    -q            Be quiet. Run test without printing anything.\n"
1610         , prog, DEFAULT_PORT);
1611 }
1612 
1613 int main(int argc, char *argv[])
1614 {
1615         struct sock_args args = {
1616                 .version = AF_INET,
1617                 .type    = SOCK_STREAM,
1618                 .port    = DEFAULT_PORT,
1619         };
1620         struct protoent *pe;
1621         unsigned int tmp;
1622         int forever = 0;
1623 
1624         /* process inputs */
1625         extern char *optarg;
1626         int rc = 0;
1627 
1628         /*
1629          * process input args
1630          */
1631 
1632         while ((rc = getopt(argc, argv, GETOPT_STR)) != -1) {
1633                 switch (rc) {
1634                 case 's':
1635                         server_mode = 1;
1636                         break;
1637                 case 'F':
1638                         forever = 1;
1639                         break;
1640                 case 'l':
1641                         args.has_local_ip = 1;
1642                         if (convert_addr(&args, optarg, ADDR_TYPE_LOCAL) < 0)
1643                                 return 1;
1644                         break;
1645                 case 'r':
1646                         args.has_remote_ip = 1;
1647                         if (convert_addr(&args, optarg, ADDR_TYPE_REMOTE) < 0)
1648                                 return 1;
1649                         break;
1650                 case 'p':
1651                         if (str_to_uint(optarg, 1, 65535, &tmp) != 0) {
1652                                 fprintf(stderr, "Invalid port\n");
1653                                 return 1;
1654                         }
1655                         args.port = (unsigned short) tmp;
1656                         break;
1657                 case 't':
1658                         if (str_to_uint(optarg, 0, INT_MAX,
1659                                         &prog_timeout) != 0) {
1660                                 fprintf(stderr, "Invalid timeout\n");
1661                                 return 1;
1662                         }
1663                         break;
1664                 case 'D':
1665                         args.type = SOCK_DGRAM;
1666                         break;
1667                 case 'R':
1668                         args.type = SOCK_RAW;
1669                         args.port = 0;
1670                         break;
1671                 case 'P':
1672                         pe = getprotobyname(optarg);
1673                         if (pe) {
1674                                 args.protocol = pe->p_proto;
1675                         } else {
1676                                 if (str_to_uint(optarg, 0, 0xffff, &tmp) != 0) {
1677                                         fprintf(stderr, "Invalid protocol\n");
1678                                         return 1;
1679                                 }
1680                                 args.protocol = tmp;
1681                         }
1682                         break;
1683                 case 'n':
1684                         iter = atoi(optarg);
1685                         break;
1686                 case 'L':
1687                         msg = random_msg(atoi(optarg));
1688                         break;
1689                 case 'M':
1690                         args.password = optarg;
1691                         break;
1692                 case 'm':
1693                         if (convert_addr(&args, optarg, ADDR_TYPE_MD5_PREFIX) < 0)
1694                                 return 1;
1695                         break;
1696                 case 'S':
1697                         args.use_setsockopt = 1;
1698                         break;
1699                 case 'C':
1700                         args.use_cmsg = 1;
1701                         break;
1702                 case 'd':
1703                         args.dev = optarg;
1704                         args.ifindex = get_ifidx(optarg);
1705                         if (args.ifindex < 0) {
1706                                 fprintf(stderr, "Invalid device name\n");
1707                                 return 1;
1708                         }
1709                         break;
1710                 case 'i':
1711                         interactive = 1;
1712                         break;
1713                 case 'g':
1714                         args.has_grp = 1;
1715                         if (convert_addr(&args, optarg, ADDR_TYPE_MCAST) < 0)
1716                                 return 1;
1717                         args.type = SOCK_DGRAM;
1718                         break;
1719                 case '6':
1720                         args.version = AF_INET6;
1721                         break;
1722                 case 'b':
1723                         args.bind_test_only = 1;
1724                         break;
1725                 case '':
1726                         args.has_expected_laddr = 1;
1727                         if (convert_addr(&args, optarg,
1728                                          ADDR_TYPE_EXPECTED_LOCAL))
1729                                 return 1;
1730                         break;
1731                 case '1':
1732                         args.has_expected_raddr = 1;
1733                         if (convert_addr(&args, optarg,
1734                                          ADDR_TYPE_EXPECTED_REMOTE))
1735                                 return 1;
1736 
1737                         break;
1738                 case '2':
1739                         if (str_to_uint(optarg, 0, INT_MAX, &tmp) == 0) {
1740                                 args.expected_ifindex = (int)tmp;
1741                         } else {
1742                                 args.expected_ifindex = get_ifidx(optarg);
1743                                 if (args.expected_ifindex < 0) {
1744                                         fprintf(stderr,
1745                                                 "Invalid expected device\n");
1746                                         return 1;
1747                                 }
1748                         }
1749                         break;
1750                 case 'q':
1751                         quiet = 1;
1752                         break;
1753                 default:
1754                         print_usage(argv[0]);
1755                         return 1;
1756                 }
1757         }
1758 
1759         if (args.password &&
1760             ((!args.has_remote_ip && !args.prefix_len) || args.type != SOCK_STREAM)) {
1761                 log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n");
1762                 return 1;
1763         }
1764 
1765         if (args.prefix_len && !args.password) {
1766                 log_error("Prefix range for MD5 protection specified without a password\n");
1767                 return 1;
1768         }
1769 
1770         if ((args.use_setsockopt || args.use_cmsg) && !args.ifindex) {
1771                 fprintf(stderr, "Device binding not specified\n");
1772                 return 1;
1773         }
1774         if (args.use_setsockopt || args.use_cmsg)
1775                 args.dev = NULL;
1776 
1777         if (iter == 0) {
1778                 fprintf(stderr, "Invalid number of messages to send\n");
1779                 return 1;
1780         }
1781 
1782         if (args.type == SOCK_STREAM && !args.protocol)
1783                 args.protocol = IPPROTO_TCP;
1784         if (args.type == SOCK_DGRAM && !args.protocol)
1785                 args.protocol = IPPROTO_UDP;
1786 
1787         if ((args.type == SOCK_STREAM || args.type == SOCK_DGRAM) &&
1788              args.port == 0) {
1789                 fprintf(stderr, "Invalid port number\n");
1790                 return 1;
1791         }
1792 
1793         if (!server_mode && !args.has_grp &&
1794             !args.has_remote_ip && !args.has_local_ip) {
1795                 fprintf(stderr,
1796                         "Local (server mode) or remote IP (client IP) required\n");
1797                 return 1;
1798         }
1799 
1800         if (interactive) {
1801                 prog_timeout = 0;
1802                 msg = NULL;
1803         }
1804 
1805         if (server_mode) {
1806                 do {
1807                         rc = do_server(&args);
1808                 } while (forever);
1809 
1810                 return rc;
1811         }
1812         return do_client(&args);
1813 }
1814 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp