Path: blob/main/tests/sys/netinet/multicast-receive.c
39483 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2025 Gleb Smirnoff <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <sys/socket.h>28#include <netinet/in.h>29#include <netinet/ip.h>30#include <arpa/inet.h>31#include <net/if.h>32#include <assert.h>33#include <errno.h>34#include <stdbool.h>35#include <stdio.h>36#include <stdlib.h>37#include <string.h>38#include <limits.h>39#include <err.h>4041static in_port_t42atop(const char *c)43{44unsigned long ul;4546errno = 0;47if ((ul = strtol(c, NULL, 10)) < 1 || ul > IPPORT_MAX || errno != 0)48err(1, "can't parse %s", c);4950return ((in_port_t)ul);51}5253int54main(int argc, char *argv[])55{56char buf[IP_MAXPACKET + 1];57struct sockaddr_in sin = {58.sin_family = AF_INET,59.sin_len = sizeof(struct sockaddr_in),60};61socklen_t slen = sizeof(struct sockaddr_in);62struct in_addr maddr, ifaddr;63ssize_t len;64int s, ifindex;65bool index;6667if (argc < 4)68usage:69errx(1, "Usage: %s (ip_mreq|ip_mreqn|group_req) "70"IPv4-group port interface", argv[0]);7172if (inet_pton(AF_INET, argv[2], &maddr) != 1)73err(1, "inet_pton(%s) failed", argv[2]);74sin.sin_port = htons(atop(argv[3]));75if (inet_pton(AF_INET, argv[4], &ifaddr) == 1)76index = false;77else if ((ifindex = if_nametoindex(argv[4])) > 0)78index = true;79else if (strcmp(argv[4], "0") == 0) {80ifindex = 0;81index = true;82} else83err(1, "if_nametoindex(%s) failed", argv[4]);8485assert((s = socket(PF_INET, SOCK_DGRAM, 0)) > 0);86assert(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0);8788if (strcmp(argv[1], "ip_mreq") == 0) {89if (index)90errx(1, "ip_mreq doesn't accept index");91struct ip_mreq mreq = {92.imr_multiaddr = maddr,93.imr_interface = ifaddr,94};95assert(setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,96sizeof(mreq)) == 0);97} else if (strcmp(argv[1], "ip_mreqn") == 0) {98/*99* ip_mreqn shall be used with index, but for testing100* purposes accept address too.101*/102struct ip_mreqn mreqn = {103.imr_multiaddr = maddr,104.imr_address = index ? (struct in_addr){ 0 } : ifaddr,105.imr_ifindex = index ? ifindex : 0,106};107assert(setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn,108sizeof(mreqn)) == 0);109} else if (strcmp(argv[1], "group_req") == 0) {110if (!index)111errx(1, "group_req expects index");112struct group_req greq = { .gr_interface = ifindex };113struct sockaddr_in *gsa = (struct sockaddr_in *)&greq.gr_group;114115gsa->sin_family = AF_INET;116gsa->sin_len = sizeof(struct sockaddr_in);117gsa->sin_addr = maddr;118assert(setsockopt(s, IPPROTO_IP, MCAST_JOIN_GROUP, &greq,119sizeof(greq)) == 0);120} else121goto usage;122123assert((len = recvfrom(s, buf, sizeof(buf) - 1, 0,124(struct sockaddr *)&sin, &slen)) > 0);125buf[len] = '\0';126printf("%s:%u %s\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), buf);127128return (0);129}130131132