packages/mini_snmpd: fix binding on IPv4 when IPv6 support is enabled
[packages.git] / net / mini_snmpd / patches / 100-dualstack.patch
1 --- a/globals.c
2 +++ b/globals.c
3 @@ -27,9 +27,9 @@
4   * Global variables
5   */
6  
7 -#ifdef __IPV4__
8  const struct in_addr inaddr_any = { INADDR_ANY };
9 -#endif
10 +
11 +int g_family = AF_INET;
12  
13  in_port_t g_udp_port = 161;
14  in_port_t g_tcp_port = 161;
15 --- a/mini_snmpd.c
16 +++ b/mini_snmpd.c
17 @@ -54,6 +54,10 @@ static void print_help(void)
18         fprintf(stderr, "-d, --disks nnn        set the disks to monitor (/)\n");
19         fprintf(stderr, "-i, --interfaces nnn   set the network interfaces to monitor (lo)\n");
20         fprintf(stderr, "-I, --listen nnn       set the network interface to listen (all)\n");
21 +#ifdef __IPV6__
22 +       fprintf(stderr, "-4, --ipv4             use IPv4 (default)\n");
23 +       fprintf(stderr, "-6, --ipv6             use IPv6\n");
24 +#endif
25         fprintf(stderr, "-t, --timeout nnn      set the timeout for MIB updates (1 second)\n");
26         fprintf(stderr, "-a, --auth             require authentication (thus SNMP version 2c)\n");
27         fprintf(stderr, "-v, --verbose          verbose syslog messages \n");
28 @@ -117,7 +121,7 @@ static void handle_udp_client(void)
29  #endif
30  
31         /* Call the protocol handler which will prepare the response packet */
32 -       inet_ntop(my_af_inet, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
33 +       inet_ntop(g_family, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
34         if (snmp(&g_udp_client) == -1) {
35                 lprintf(LOG_WARNING, "could not handle packet from UDP client %s:%d: %m\n",
36                         straddr, sockaddr.my_sin_port);
37 @@ -132,7 +136,7 @@ static void handle_udp_client(void)
38         /* Send the whole UDP packet to the socket at once */
39         rv = sendto(g_udp_sockfd, g_udp_client.packet, g_udp_client.size,
40                 MSG_DONTWAIT, (struct sockaddr *)&sockaddr, socklen);
41 -       inet_ntop(my_af_inet, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
42 +       inet_ntop(g_family, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
43         if (rv == -1) {
44                 lprintf(LOG_WARNING, "could not send packet to UDP client %s:%d: %m\n",
45                         straddr, sockaddr.my_sin_port);
46 @@ -176,7 +180,7 @@ static void handle_tcp_connect(void)
47                 }
48                 tmp_sockaddr.my_sin_addr = client->addr;
49                 tmp_sockaddr.my_sin_port = client->port;
50 -               inet_ntop(my_af_inet, &tmp_sockaddr.my_sin_addr, straddr, sizeof(straddr));
51 +               inet_ntop(g_family, &tmp_sockaddr.my_sin_addr, straddr, sizeof(straddr));
52                 lprintf(LOG_WARNING, "maximum number of %d clients reached, kicking out %s:%d\n",
53                         MAX_NR_CLIENTS, straddr, tmp_sockaddr.my_sin_port);
54                 close(client->sockfd);
55 @@ -190,7 +194,7 @@ static void handle_tcp_connect(void)
56         }
57  
58         /* Now fill out the client control structure values */
59 -       inet_ntop(my_af_inet, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
60 +       inet_ntop(g_family, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
61         lprintf(LOG_DEBUG, "connected TCP client %s:%d\n",
62                 straddr, sockaddr.my_sin_port);
63         client->timestamp = time(NULL);
64 @@ -211,7 +215,7 @@ static void handle_tcp_client_write(clie
65         sockaddr.my_sin_addr = client->addr;
66         sockaddr.my_sin_port = client->port;
67         rv = send(client->sockfd, client->packet, client->size, 0);
68 -       inet_ntop(my_af_inet, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
69 +       inet_ntop(g_family, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
70         if (rv == -1) {
71                 lprintf(LOG_WARNING, "could not send packet to TCP client %s:%d: %m\n",
72                         straddr, sockaddr.my_sin_port);
73 @@ -246,7 +250,7 @@ static void handle_tcp_client_read(clien
74         sockaddr.my_sin_port = client->port;
75         rv = read(client->sockfd, client->packet + client->size,
76                 sizeof (client->packet) - client->size);
77 -       inet_ntop(my_af_inet, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
78 +       inet_ntop(g_family, &sockaddr.my_sin_addr, straddr, sizeof(straddr));
79         if (rv == -1) {
80                 lprintf(LOG_WARNING, "could not read packet from TCP client %s:%d: %m\n",
81                         straddr, sockaddr.my_sin_port);
82 @@ -304,7 +308,11 @@ static void handle_tcp_client_read(clien
83  
84  int main(int argc, char *argv[])
85  {
86 +#ifdef __IPV6__
87 +       static const char short_options[] = "p:P:c:D:V:L:C:d:i:I:t:T:avl46h";
88 +#else
89         static const char short_options[] = "p:P:c:D:V:L:C:d:i:I:t:T:avlh";
90 +#endif
91         static const struct option long_options[] = {
92                 { "udp-port", 1, 0, 'p' },
93                 { "tcp-port", 1, 0, 'P' },
94 @@ -316,6 +324,10 @@ int main(int argc, char *argv[])
95                 { "disks", 1, 0, 'd' },
96                 { "interfaces", 1, 0, 'i' },
97                 { "listen", 1, 0, 'I' },
98 +#ifdef __IPV6__
99 +               { "ipv4", 0, 0, '4' },
100 +               { "ipv6", 0, 0, '6' },
101 +#endif
102                 { "timeout", 1, 0, 't' },
103                 { "traps", 1, 0, 'T' },
104                 { "auth", 0, 0, 'a' },
105 @@ -327,7 +339,12 @@ int main(int argc, char *argv[])
106         int option_index = 1;
107         int c;
108  
109 -       struct my_sockaddr_t sockaddr;
110 +       union {
111 +               struct sockaddr_in sa;
112 +#ifdef __IPV6__
113 +               struct sockaddr_in6 sa6;
114 +#endif
115 +       } sockaddr;
116         my_socklen_t socklen;
117         struct timeval tv_last;
118         struct timeval tv_now;
119 @@ -396,6 +413,14 @@ int main(int argc, char *argv[])
120                         case 'v':
121                                 g_verbose = 1;
122                                 break;
123 +#ifdef __IPV6__
124 +                       case '4':
125 +                               g_family = AF_INET;
126 +                               break;
127 +                       case '6':
128 +                               g_family = AF_INET6;
129 +                               break;
130 +#endif
131                         case 'l':
132                                 print_version();
133                                 exit(EXIT_ARGS);
134 @@ -435,15 +460,24 @@ int main(int argc, char *argv[])
135  #endif
136  
137         /* Open the server's UDP port and prepare it for listening */
138 -       g_udp_sockfd = socket(my_pf_inet, SOCK_DGRAM, 0);
139 +       g_udp_sockfd = socket((g_family == AF_INET) ? PF_INET : PF_INET6, SOCK_DGRAM, 0);
140         if (g_udp_sockfd == -1) {
141                 lprintf(LOG_ERR, "could not create UDP socket: %m\n");
142                 exit(EXIT_SYSCALL);
143         }
144 -       sockaddr.my_sin_family = my_af_inet;
145 -       sockaddr.my_sin_port = htons(g_udp_port);
146 -       sockaddr.my_sin_addr = my_inaddr_any;
147 -       socklen = sizeof (sockaddr);
148 +       if (g_family == AF_INET) {
149 +               sockaddr.sa.sin_family = g_family;
150 +               sockaddr.sa.sin_port = htons(g_udp_port);
151 +               sockaddr.sa.sin_addr = inaddr_any;
152 +               socklen = sizeof(sockaddr.sa);
153 +#ifdef __IPV6__
154 +       } else {
155 +               sockaddr.sa6.sin6_family = g_family;
156 +               sockaddr.sa6.sin6_port = htons(g_udp_port);
157 +               sockaddr.sa6.sin6_addr = in6addr_any;
158 +               socklen = sizeof(sockaddr.sa6);
159 +#endif
160 +       }
161         if (bind(g_udp_sockfd, (struct sockaddr *)&sockaddr, socklen) == -1) {
162                 lprintf(LOG_ERR, "could not bind UDP socket to port %d: %m\n", g_udp_port);
163                 exit(EXIT_SYSCALL);
164 @@ -457,7 +491,7 @@ int main(int argc, char *argv[])
165         }
166  
167         /* Open the server's TCP port and prepare it for listening */
168 -       g_tcp_sockfd = socket(my_pf_inet, SOCK_STREAM, 0);
169 +       g_tcp_sockfd = socket((g_family == AF_INET) ? PF_INET : PF_INET6, SOCK_STREAM, 0);
170         if (g_tcp_sockfd == -1) {
171                 lprintf(LOG_ERR, "could not create TCP socket: %m\n");
172                 exit(EXIT_SYSCALL);
173 @@ -474,10 +508,19 @@ int main(int argc, char *argv[])
174                 lprintf(LOG_WARNING, "could not set SO_REUSEADDR on TCP socket: %m\n");
175                 exit(EXIT_SYSCALL);
176         }
177 -       sockaddr.my_sin_family = my_af_inet;
178 -       sockaddr.my_sin_port = htons(g_tcp_port);
179 -       sockaddr.my_sin_addr = my_inaddr_any;
180 -       socklen = sizeof (sockaddr);
181 +       if (g_family == AF_INET) {
182 +               sockaddr.sa.sin_family = g_family;
183 +               sockaddr.sa.sin_port = htons(g_udp_port);
184 +               sockaddr.sa.sin_addr = inaddr_any;
185 +               socklen = sizeof(sockaddr.sa);
186 +#ifdef __IPV6__
187 +       } else {
188 +               sockaddr.sa6.sin6_family = g_family;
189 +               sockaddr.sa6.sin6_port = htons(g_udp_port);
190 +               sockaddr.sa6.sin6_addr = in6addr_any;
191 +               socklen = sizeof(sockaddr.sa6);
192 +#endif
193 +       }
194         if (bind(g_tcp_sockfd, (struct sockaddr *)&sockaddr, socklen) == -1) {
195                 lprintf(LOG_ERR, "could not bind TCP socket to port %d: %m\n", g_tcp_port);
196                 exit(EXIT_SYSCALL);
197 --- a/mini_snmpd.h
198 +++ b/mini_snmpd.h
199 @@ -255,6 +255,7 @@ typedef struct demoinfo_s {
200  
201  extern in_port_t g_udp_port;
202  extern in_port_t g_tcp_port;
203 +extern int g_family;
204  extern int g_timeout;
205  extern int g_auth;
206  extern int g_verbose;
207 @@ -265,9 +266,9 @@ extern char *g_vendor;
208  extern char *g_location;
209  extern char *g_contact;
210  extern char *g_bind_to_device;
211 -#ifdef __IPV4__
212 +
213  extern const struct in_addr inaddr_any;
214 -#endif
215 +
216  
217  extern char *g_disk_list[MAX_NR_DISKS];
218  extern int g_disk_list_length;