1 1.36 riastrad /* $NetBSD: socketops.c,v 1.36 2022/06/26 17:55:38 riastradh Exp $ */ 2 1.1 kefren 3 1.17 kefren /* 4 1.1 kefren * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 1.1 kefren * All rights reserved. 6 1.1 kefren * 7 1.1 kefren * This code is derived from software contributed to The NetBSD Foundation 8 1.1 kefren * by Mihai Chelaru <kefren (at) NetBSD.org> 9 1.1 kefren * 10 1.1 kefren * Redistribution and use in source and binary forms, with or without 11 1.1 kefren * modification, are permitted provided that the following conditions 12 1.1 kefren * are met: 13 1.1 kefren * 1. Redistributions of source code must retain the above copyright 14 1.1 kefren * notice, this list of conditions and the following disclaimer. 15 1.1 kefren * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 kefren * notice, this list of conditions and the following disclaimer in the 17 1.1 kefren * documentation and/or other materials provided with the distribution. 18 1.1 kefren * 19 1.1 kefren * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 kefren * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 kefren * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 kefren * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 kefren * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 kefren * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 kefren * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 kefren * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 kefren * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 kefren * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 kefren * POSSIBILITY OF SUCH DAMAGE. 30 1.1 kefren */ 31 1.1 kefren 32 1.1 kefren #include <sys/types.h> 33 1.1 kefren #include <sys/stat.h> 34 1.1 kefren #include <sys/socket.h> 35 1.1 kefren #include <sys/ioctl.h> 36 1.1 kefren #include <net/if.h> 37 1.1 kefren #include <netinet/in.h> 38 1.1 kefren #include <arpa/inet.h> 39 1.1 kefren 40 1.7 kefren #include <assert.h> 41 1.1 kefren #include <errno.h> 42 1.7 kefren #include <ifaddrs.h> 43 1.7 kefren #include <poll.h> 44 1.1 kefren #include <signal.h> 45 1.7 kefren #include <stdio.h> 46 1.1 kefren #include <stdlib.h> 47 1.7 kefren #include <strings.h> 48 1.1 kefren #include <unistd.h> 49 1.1 kefren 50 1.20 kefren #include "conffile.h" 51 1.1 kefren #include "fsm.h" 52 1.1 kefren #include "ldp.h" 53 1.1 kefren #include "ldp_command.h" 54 1.1 kefren #include "tlv.h" 55 1.1 kefren #include "ldp_peer.h" 56 1.1 kefren #include "notifications.h" 57 1.1 kefren #include "tlv_stack.h" 58 1.1 kefren #include "mpls_interface.h" 59 1.1 kefren #include "label.h" 60 1.1 kefren #include "mpls_routes.h" 61 1.1 kefren #include "ldp_errors.h" 62 1.1 kefren #include "socketops.h" 63 1.1 kefren 64 1.35 joerg struct hello_info_head hello_info_head; 65 1.35 joerg static SLIST_HEAD(,hello_socket) hello_socket_head; 66 1.35 joerg 67 1.12 kefren int ls; /* TCP listening socket on port 646 */ 68 1.12 kefren int route_socket; /* used to see when a route is added/deleted */ 69 1.12 kefren int command_socket; /* Listening socket for interface command */ 70 1.12 kefren int current_msg_id = 0x233; 71 1.12 kefren int command_port = LDP_COMMAND_PORT; 72 1.1 kefren extern int replay_index; 73 1.1 kefren extern struct rt_msg replay_rt[REPLAY_MAX]; 74 1.1 kefren extern struct com_sock csockets[MAX_COMMAND_SOCKETS]; 75 1.1 kefren 76 1.1 kefren int ldp_hello_time = LDP_HELLO_TIME; 77 1.3 kefren int ldp_keepalive_time = LDP_KEEPALIVE_TIME; 78 1.3 kefren int ldp_holddown_time = LDP_HOLDTIME; 79 1.7 kefren int no_default_route = 1; 80 1.12 kefren int loop_detection = 0; 81 1.24 kefren bool may_connect; 82 1.1 kefren 83 1.1 kefren void recv_pdu(int); 84 1.1 kefren void send_hello_alarm(int); 85 1.11 joerg __dead static void bail_out(int); 86 1.29 kefren static void print_info(int); 87 1.17 kefren static int bind_socket(int s, int stype); 88 1.12 kefren static int set_tos(int); 89 1.12 kefren static int socket_reuse_port(int); 90 1.1 kefren static int get_local_addr(struct sockaddr_dl *, struct in_addr *); 91 1.17 kefren static int is_hello_socket(int); 92 1.28 kefren static int is_passive_if(const char *if_name); 93 1.1 kefren 94 1.1 kefren int 95 1.12 kefren create_hello_sockets() 96 1.1 kefren { 97 1.1 kefren struct ip_mreq mcast_addr; 98 1.17 kefren int s, joined_groups; 99 1.18 kefren struct ifaddrs *ifa, *ifb; 100 1.18 kefren uint lastifindex; 101 1.12 kefren #ifdef INET6 102 1.12 kefren struct ipv6_mreq mcast_addr6; 103 1.17 kefren struct sockaddr_in6 *if_sa6; 104 1.12 kefren #endif 105 1.17 kefren struct hello_socket *hs; 106 1.17 kefren 107 1.17 kefren SLIST_INIT(&hello_socket_head); 108 1.1 kefren 109 1.12 kefren s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 110 1.1 kefren if (s < 0) 111 1.1 kefren return s; 112 1.17 kefren debugp("INET4 socket created (%d)\n", s); 113 1.1 kefren /* 114 1.12 kefren * RFC5036 specifies we should listen to all subnet routers multicast 115 1.1 kefren * group 116 1.1 kefren */ 117 1.19 kefren mcast_addr.imr_multiaddr.s_addr = htonl(INADDR_ALLRTRS_GROUP); 118 1.12 kefren 119 1.12 kefren if (socket_reuse_port(s) < 0) 120 1.12 kefren goto chs_error; 121 1.17 kefren /* Bind it to port 646 */ 122 1.17 kefren if (bind_socket(s, AF_INET) == -1) { 123 1.12 kefren warnp("Cannot bind INET hello socket\n"); 124 1.12 kefren goto chs_error; 125 1.12 kefren } 126 1.12 kefren 127 1.1 kefren /* We don't need to receive back our messages */ 128 1.16 kefren if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &(u_char){0}, 129 1.16 kefren sizeof(u_char)) == -1) { 130 1.12 kefren fatalp("INET setsockopt IP_MCAST_LOOP: %s\n", strerror(errno)); 131 1.12 kefren goto chs_error; 132 1.12 kefren } 133 1.17 kefren /* Finally join the group on all interfaces */ 134 1.17 kefren if (getifaddrs(&ifa) == -1) { 135 1.17 kefren fatalp("Cannot iterate interfaces\n"); 136 1.17 kefren return -1; 137 1.17 kefren } 138 1.17 kefren lastifindex = UINT_MAX; 139 1.17 kefren joined_groups = 0; 140 1.17 kefren for (ifb = ifa; ifb; ifb = ifb->ifa_next) { 141 1.17 kefren struct sockaddr_in *if_sa = (struct sockaddr_in *) ifb->ifa_addr; 142 1.17 kefren if (if_sa->sin_family != AF_INET || (!(ifb->ifa_flags & IFF_UP)) || 143 1.17 kefren (ifb->ifa_flags & IFF_LOOPBACK) || 144 1.20 kefren (!(ifb->ifa_flags & IFF_MULTICAST)) || 145 1.17 kefren (ntohl(if_sa->sin_addr.s_addr) >> 24 == IN_LOOPBACKNET) || 146 1.20 kefren is_passive_if(ifb->ifa_name) || 147 1.17 kefren lastifindex == if_nametoindex(ifb->ifa_name)) 148 1.17 kefren continue; 149 1.17 kefren lastifindex = if_nametoindex(ifb->ifa_name); 150 1.17 kefren 151 1.17 kefren mcast_addr.imr_interface.s_addr = if_sa->sin_addr.s_addr; 152 1.17 kefren debugp("Join IPv4 mcast on %s\n", ifb->ifa_name); 153 1.17 kefren if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mcast_addr, 154 1.17 kefren sizeof(mcast_addr)) == -1) { 155 1.17 kefren fatalp("setsockopt ADD_MEMBER: %s\n", strerror(errno)); 156 1.17 kefren goto chs_error; 157 1.17 kefren } 158 1.17 kefren joined_groups++; 159 1.17 kefren if (joined_groups == IP_MAX_MEMBERSHIPS) { 160 1.17 kefren warnp("Maximum group memberships reached for INET socket\n"); 161 1.17 kefren break; 162 1.17 kefren } 163 1.17 kefren } 164 1.17 kefren /* TTL:1 for IPv4 */ 165 1.17 kefren if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &(int){1}, 166 1.17 kefren sizeof(int)) == -1) { 167 1.17 kefren fatalp("set mcast ttl: %s\n", strerror(errno)); 168 1.17 kefren goto chs_error; 169 1.17 kefren } 170 1.17 kefren /* TOS :0xc0 for IPv4 */ 171 1.17 kefren if (set_tos(s) == -1) { 172 1.17 kefren fatalp("set_tos: %s", strerror(errno)); 173 1.17 kefren goto chs_error; 174 1.17 kefren } 175 1.17 kefren /* we need to get the input interface for message processing */ 176 1.17 kefren if (setsockopt(s, IPPROTO_IP, IP_RECVIF, &(uint32_t){1}, 177 1.12 kefren sizeof(uint32_t)) == -1) { 178 1.17 kefren fatalp("Cannot set IP_RECVIF\n"); 179 1.12 kefren goto chs_error; 180 1.1 kefren } 181 1.12 kefren 182 1.17 kefren hs = (struct hello_socket *)malloc(sizeof(*hs)); 183 1.17 kefren if (hs == NULL) { 184 1.17 kefren fatalp("Cannot alloc hello_socket structure\n"); 185 1.12 kefren goto chs_error; 186 1.17 kefren } 187 1.17 kefren hs->type = AF_INET; 188 1.17 kefren hs->socket = s; 189 1.17 kefren SLIST_INSERT_HEAD(&hello_socket_head, hs, listentry); 190 1.17 kefren 191 1.12 kefren #ifdef INET6 192 1.17 kefren /* 193 1.17 kefren * Now we do the same for IPv6 194 1.17 kefren */ 195 1.17 kefren s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 196 1.17 kefren if (s < 0) { 197 1.17 kefren fatalp("Cannot create INET6 socket\n"); 198 1.17 kefren return -1; 199 1.12 kefren } 200 1.17 kefren debugp("INET6 socket created (%d)\n", s); 201 1.17 kefren 202 1.17 kefren if (socket_reuse_port(s) < 0) 203 1.12 kefren goto chs_error; 204 1.17 kefren 205 1.17 kefren if (bind_socket(s, AF_INET6) == -1) { 206 1.17 kefren fatalp("Cannot bind INET6 hello socket\n"); 207 1.12 kefren goto chs_error; 208 1.17 kefren } 209 1.17 kefren 210 1.17 kefren if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 211 1.17 kefren &(uint){0}, sizeof(uint)) == -1) { 212 1.17 kefren fatalp("INET6 setsocketopt IP_MCAST_LOOP: %s\n", 213 1.17 kefren strerror(errno)); 214 1.12 kefren goto chs_error; 215 1.1 kefren } 216 1.12 kefren 217 1.17 kefren lastifindex = UINT_MAX; 218 1.19 kefren mcast_addr6.ipv6mr_multiaddr = in6addr_linklocal_allrouters; 219 1.17 kefren for (ifb = ifa; ifb; ifb = ifb->ifa_next) { 220 1.17 kefren if_sa6 = (struct sockaddr_in6 *) ifb->ifa_addr; 221 1.17 kefren if (if_sa6->sin6_family != AF_INET6 || 222 1.17 kefren (!(ifb->ifa_flags & IFF_UP)) || 223 1.20 kefren (!(ifb->ifa_flags & IFF_MULTICAST)) || 224 1.17 kefren (ifb->ifa_flags & IFF_LOOPBACK) || 225 1.20 kefren is_passive_if(ifb->ifa_name) || 226 1.17 kefren IN6_IS_ADDR_LOOPBACK(&if_sa6->sin6_addr)) 227 1.17 kefren continue; 228 1.17 kefren /* 229 1.17 kefren * draft-ietf-mpls-ldp-ipv6-07 Section 5.1: 230 1.17 kefren * Additionally, the link-local 231 1.17 kefren * IPv6 address MUST be used as the source IP address in IPv6 232 1.17 kefren * LDP Link Hellos. 233 1.17 kefren */ 234 1.17 kefren if (IN6_IS_ADDR_LINKLOCAL(&if_sa6->sin6_addr) == 0) 235 1.17 kefren continue; 236 1.17 kefren /* We should have only one LLADDR per interface, but... */ 237 1.17 kefren if (lastifindex == if_nametoindex(ifb->ifa_name)) 238 1.17 kefren continue; 239 1.17 kefren mcast_addr6.ipv6mr_interface = lastifindex = 240 1.17 kefren if_nametoindex(ifb->ifa_name); 241 1.17 kefren 242 1.17 kefren debugp("Join IPv6 mcast on %s\n", ifb->ifa_name); 243 1.17 kefren if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, 244 1.17 kefren (char *)&mcast_addr6, sizeof(mcast_addr6)) == -1) { 245 1.17 kefren fatalp("INET6 setsockopt JOIN: %s\n", strerror(errno)); 246 1.17 kefren goto chs_error; 247 1.17 kefren } 248 1.17 kefren } 249 1.17 kefren freeifaddrs(ifa); 250 1.17 kefren 251 1.17 kefren /* TTL: 255 for IPv6 - draft-ietf-mpls-ldp-ipv6-07 Section 9 */ 252 1.17 kefren if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 253 1.17 kefren &(int){255}, sizeof(int)) == -1) { 254 1.17 kefren fatalp("set mcast hops: %s\n", strerror(errno)); 255 1.12 kefren goto chs_error; 256 1.1 kefren } 257 1.17 kefren if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, 258 1.17 kefren &(uint32_t){1}, sizeof(uint32_t)) == -1) 259 1.17 kefren goto chs_error; 260 1.17 kefren 261 1.17 kefren hs = (struct hello_socket *)malloc(sizeof(*hs)); 262 1.17 kefren if (hs == NULL) { 263 1.17 kefren fatalp("Memory alloc problem: hs\n"); 264 1.12 kefren goto chs_error; 265 1.17 kefren } 266 1.17 kefren 267 1.17 kefren hs->type = AF_INET6; 268 1.17 kefren hs->socket = s; 269 1.17 kefren SLIST_INSERT_HEAD(&hello_socket_head, hs, listentry); 270 1.12 kefren #endif 271 1.12 kefren return 0; 272 1.12 kefren chs_error: 273 1.12 kefren close(s); 274 1.12 kefren return -1; 275 1.1 kefren } 276 1.1 kefren 277 1.17 kefren /* Check if parameter is a hello socket */ 278 1.17 kefren int 279 1.17 kefren is_hello_socket(int s) 280 1.17 kefren { 281 1.17 kefren struct hello_socket *hs; 282 1.17 kefren 283 1.17 kefren SLIST_FOREACH(hs, &hello_socket_head, listentry) 284 1.17 kefren if (hs->socket == s) 285 1.17 kefren return 1; 286 1.17 kefren return 0; 287 1.17 kefren } 288 1.17 kefren 289 1.20 kefren /* Check if interface is passive */ 290 1.20 kefren static int 291 1.28 kefren is_passive_if(const char *if_name) 292 1.20 kefren { 293 1.32 kefren struct conf_interface *coif; 294 1.20 kefren 295 1.32 kefren SLIST_FOREACH(coif, &coifs_head, iflist) 296 1.32 kefren if (strncasecmp(if_name, coif->if_name, IF_NAMESIZE) == 0 && 297 1.32 kefren coif->passive != 0) 298 1.20 kefren return 1; 299 1.20 kefren return 0; 300 1.20 kefren } 301 1.20 kefren 302 1.1 kefren /* Sets the TTL to 1 as we don't want to transmit outside this subnet */ 303 1.12 kefren int 304 1.1 kefren set_ttl(int s) 305 1.1 kefren { 306 1.1 kefren int ret; 307 1.1 kefren if ((ret = setsockopt(s, IPPROTO_IP, IP_TTL, &(int){1}, sizeof(int))) 308 1.1 kefren == -1) 309 1.1 kefren fatalp("set_ttl: %s", strerror(errno)); 310 1.1 kefren return ret; 311 1.1 kefren } 312 1.1 kefren 313 1.1 kefren /* Sets TOS to 0xc0 aka IP Precedence 6 */ 314 1.12 kefren static int 315 1.1 kefren set_tos(int s) 316 1.1 kefren { 317 1.1 kefren int ret; 318 1.1 kefren if ((ret = setsockopt(s, IPPROTO_IP, IP_TOS, &(int){0xc0}, 319 1.1 kefren sizeof(int))) == -1) 320 1.1 kefren fatalp("set_tos: %s", strerror(errno)); 321 1.1 kefren return ret; 322 1.1 kefren } 323 1.1 kefren 324 1.12 kefren static int 325 1.1 kefren socket_reuse_port(int s) 326 1.1 kefren { 327 1.12 kefren int ret; 328 1.1 kefren if ((ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &(int){1}, 329 1.1 kefren sizeof(int))) == -1) 330 1.1 kefren fatalp("socket_reuse_port: %s", strerror(errno)); 331 1.1 kefren return ret; 332 1.1 kefren } 333 1.1 kefren 334 1.1 kefren /* binds an UDP socket */ 335 1.12 kefren static int 336 1.17 kefren bind_socket(int s, int stype) 337 1.1 kefren { 338 1.16 kefren union sockunion su; 339 1.12 kefren 340 1.17 kefren assert (stype == AF_INET || stype == AF_INET6); 341 1.1 kefren 342 1.33 mrg memset(&su, 0, sizeof su); 343 1.17 kefren if (stype == AF_INET) { 344 1.16 kefren su.sin.sin_len = sizeof(su.sin); 345 1.16 kefren su.sin.sin_family = AF_INET; 346 1.17 kefren su.sin.sin_addr.s_addr = htonl(INADDR_ANY); 347 1.16 kefren su.sin.sin_port = htons(LDP_PORT); 348 1.12 kefren } 349 1.12 kefren #ifdef INET6 350 1.17 kefren else if (stype == AF_INET6) { 351 1.16 kefren su.sin6.sin6_len = sizeof(su.sin6); 352 1.16 kefren su.sin6.sin6_family = AF_INET6; 353 1.16 kefren su.sin6.sin6_addr = in6addr_any; 354 1.16 kefren su.sin6.sin6_port = htons(LDP_PORT); 355 1.12 kefren } 356 1.12 kefren #endif 357 1.16 kefren if (bind(s, &su.sa, su.sa.sa_len)) { 358 1.12 kefren fatalp("bind_socket: %s\n", strerror(errno)); 359 1.1 kefren return -1; 360 1.1 kefren } 361 1.1 kefren return 0; 362 1.1 kefren } 363 1.1 kefren 364 1.1 kefren /* Create / bind the TCP socket */ 365 1.12 kefren int 366 1.1 kefren create_listening_socket(void) 367 1.1 kefren { 368 1.1 kefren struct sockaddr_in sa; 369 1.1 kefren int s; 370 1.1 kefren 371 1.1 kefren sa.sin_len = sizeof(sa); 372 1.1 kefren sa.sin_family = AF_INET; 373 1.1 kefren sa.sin_port = htons(LDP_PORT); 374 1.1 kefren sa.sin_addr.s_addr = htonl(INADDR_ANY); 375 1.1 kefren 376 1.12 kefren s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 377 1.1 kefren if (s < 0) 378 1.1 kefren return s; 379 1.1 kefren if (bind(s, (struct sockaddr *) & sa, sizeof(sa))) { 380 1.1 kefren fatalp("bind: %s", strerror(errno)); 381 1.1 kefren close(s); 382 1.1 kefren return -1; 383 1.1 kefren } 384 1.1 kefren if (listen(s, 10) == -1) { 385 1.1 kefren fatalp("listen: %s", strerror(errno)); 386 1.1 kefren close(s); 387 1.1 kefren return -1; 388 1.1 kefren } 389 1.1 kefren /* if (set_tos(s) == -1) { 390 1.1 kefren fatalp("set_tos: %s", strerror(errno)); 391 1.1 kefren close(s); 392 1.1 kefren return -1; 393 1.1 kefren } 394 1.1 kefren */ return s; 395 1.1 kefren } 396 1.1 kefren 397 1.1 kefren /* 398 1.1 kefren * It's ugly. We need a function to pass all tlvs and create pdu but since I 399 1.1 kefren * use UDP socket only to send hellos, I didn't bother 400 1.1 kefren */ 401 1.1 kefren void 402 1.1 kefren send_hello(void) 403 1.1 kefren { 404 1.1 kefren struct hello_tlv *t; 405 1.1 kefren struct common_hello_tlv *cht; 406 1.1 kefren struct ldp_pdu *spdu; 407 1.36 riastrad struct in_addr ldp_id; 408 1.1 kefren struct transport_address_tlv *trtlv; 409 1.1 kefren void *v; 410 1.1 kefren struct sockaddr_in sadest; /* Destination ALL_ROUTERS */ 411 1.12 kefren ssize_t sb = 0; /* sent bytes */ 412 1.1 kefren struct ifaddrs *ifa, *ifb; 413 1.1 kefren struct sockaddr_in *if_sa; 414 1.17 kefren int ip4socket = -1; 415 1.17 kefren uint lastifindex; 416 1.17 kefren struct hello_socket *hs; 417 1.32 kefren struct conf_interface *coif; 418 1.32 kefren bool bad_tr_addr; 419 1.12 kefren #ifdef INET6 420 1.12 kefren struct sockaddr_in6 sadest6; 421 1.17 kefren int ip6socket = -1; 422 1.12 kefren #endif 423 1.1 kefren 424 1.12 kefren #define BASIC_HELLO_MSG_SIZE (sizeof(struct ldp_pdu) + /* PDU */ \ 425 1.1 kefren TLV_TYPE_LENGTH + MSGID_SIZE + /* Hello TLV */ \ 426 1.1 kefren /* Common Hello TLV */ \ 427 1.12 kefren sizeof(struct common_hello_tlv)) 428 1.12 kefren #define GENERAL_HELLO_MSG_SIZE BASIC_HELLO_MSG_SIZE + \ 429 1.12 kefren /* Transport Address */ \ 430 1.12 kefren sizeof(struct transport_address_tlv) 431 1.12 kefren #define IPV4_HELLO_MSG_SIZE BASIC_HELLO_MSG_SIZE + 4 + sizeof(struct in_addr) 432 1.12 kefren #define IPV6_HELLO_MSG_SIZE BASIC_HELLO_MSG_SIZE + 4 + sizeof(struct in6_addr) 433 1.1 kefren 434 1.12 kefren if ((v = calloc(1, GENERAL_HELLO_MSG_SIZE)) == NULL) { 435 1.12 kefren fatalp("alloc problem in send_hello()\n"); 436 1.1 kefren return; 437 1.1 kefren } 438 1.1 kefren 439 1.1 kefren spdu = (struct ldp_pdu *)((char *)v); 440 1.1 kefren t = (struct hello_tlv *)(spdu + 1); 441 1.1 kefren cht = &t->ch; /* Hello tlv struct includes CHT */ 442 1.1 kefren trtlv = (struct transport_address_tlv *)(t + 1); 443 1.1 kefren 444 1.1 kefren /* Prepare PDU envelope */ 445 1.1 kefren spdu->version = htons(LDP_VERSION); 446 1.12 kefren spdu->length = htons(IPV4_HELLO_MSG_SIZE - PDU_VER_LENGTH); 447 1.36 riastrad inet_aton(LDP_ID, &ldp_id); 448 1.36 riastrad spdu->ldp_id = ldp_id; 449 1.1 kefren 450 1.1 kefren /* Prepare Hello TLV */ 451 1.1 kefren t->type = htons(LDP_HELLO); 452 1.1 kefren t->length = htons(MSGID_SIZE + 453 1.1 kefren sizeof(struct common_hello_tlv) + 454 1.12 kefren IPV4_HELLO_MSG_SIZE - BASIC_HELLO_MSG_SIZE); 455 1.1 kefren /* 456 1.28 kefren * We used ID 0 instead of htonl(get_message_id()) because we've 457 1.12 kefren * seen hellos from Cisco routers doing the same thing 458 1.1 kefren */ 459 1.1 kefren t->messageid = 0; 460 1.1 kefren 461 1.1 kefren /* Prepare Common Hello attributes */ 462 1.1 kefren cht->type = htons(TLV_COMMON_HELLO); 463 1.1 kefren cht->length = htons(sizeof(cht->holdtime) + sizeof(cht->res)); 464 1.3 kefren cht->holdtime = htons(ldp_holddown_time); 465 1.1 kefren cht->res = 0; 466 1.1 kefren 467 1.1 kefren /* 468 1.12 kefren * Prepare Transport Address TLV RFC5036 says: "If this optional TLV 469 1.1 kefren * is not present the IPv4 source address for the UDP packet carrying 470 1.1 kefren * the Hello should be used." But we send it because everybody seems 471 1.1 kefren * to do so 472 1.1 kefren */ 473 1.1 kefren trtlv->type = htons(TLV_IPV4_TRANSPORT); 474 1.1 kefren trtlv->length = htons(sizeof(struct in_addr)); 475 1.1 kefren /* trtlv->address will be set for each socket */ 476 1.1 kefren 477 1.1 kefren /* Destination sockaddr */ 478 1.1 kefren memset(&sadest, 0, sizeof(sadest)); 479 1.1 kefren sadest.sin_len = sizeof(sadest); 480 1.1 kefren sadest.sin_family = AF_INET; 481 1.1 kefren sadest.sin_port = htons(LDP_PORT); 482 1.19 kefren sadest.sin_addr.s_addr = htonl(INADDR_ALLRTRS_GROUP); 483 1.1 kefren 484 1.17 kefren /* Find our socket */ 485 1.17 kefren SLIST_FOREACH(hs, &hello_socket_head, listentry) 486 1.17 kefren if (hs->type == AF_INET) { 487 1.17 kefren ip4socket = hs->socket; 488 1.17 kefren break; 489 1.17 kefren } 490 1.17 kefren assert(ip4socket >= 0); 491 1.17 kefren 492 1.1 kefren if (getifaddrs(&ifa) == -1) { 493 1.1 kefren free(v); 494 1.17 kefren fatalp("Cannot enumerate interfaces\n"); 495 1.1 kefren return; 496 1.1 kefren } 497 1.1 kefren 498 1.17 kefren lastifindex = UINT_MAX; 499 1.12 kefren /* Loop all interfaces in order to send IPv4 hellos */ 500 1.1 kefren for (ifb = ifa; ifb; ifb = ifb->ifa_next) { 501 1.1 kefren if_sa = (struct sockaddr_in *) ifb->ifa_addr; 502 1.20 kefren if (if_sa->sin_family != AF_INET || 503 1.20 kefren (!(ifb->ifa_flags & IFF_UP)) || 504 1.20 kefren (ifb->ifa_flags & IFF_LOOPBACK) || 505 1.20 kefren (!(ifb->ifa_flags & IFF_MULTICAST)) || 506 1.20 kefren is_passive_if(ifb->ifa_name) || 507 1.20 kefren (ntohl(if_sa->sin_addr.s_addr) >> 24 == IN_LOOPBACKNET) || 508 1.20 kefren lastifindex == if_nametoindex(ifb->ifa_name)) 509 1.1 kefren continue; 510 1.12 kefren 511 1.12 kefren /* Send only once per interface, using primary address */ 512 1.17 kefren if (lastifindex == if_nametoindex(ifb->ifa_name)) 513 1.1 kefren continue; 514 1.32 kefren /* Check if there is transport address set for this interface */ 515 1.32 kefren bad_tr_addr = false; 516 1.32 kefren SLIST_FOREACH(coif, &coifs_head, iflist) 517 1.32 kefren if (strncasecmp(coif->if_name, ifb->ifa_name, 518 1.32 kefren IF_NAMESIZE) == 0 && 519 1.32 kefren coif->tr_addr.s_addr != 0 && 520 1.32 kefren coif->tr_addr.s_addr != if_sa->sin_addr.s_addr) 521 1.32 kefren bad_tr_addr = true; 522 1.32 kefren if (bad_tr_addr == true) 523 1.32 kefren continue; 524 1.17 kefren lastifindex = if_nametoindex(ifb->ifa_name); 525 1.17 kefren 526 1.17 kefren if (setsockopt(ip4socket, IPPROTO_IP, IP_MULTICAST_IF, 527 1.1 kefren &if_sa->sin_addr, sizeof(struct in_addr)) == -1) { 528 1.1 kefren warnp("setsockopt failed: %s\n", strerror(errno)); 529 1.1 kefren continue; 530 1.1 kefren } 531 1.12 kefren trtlv->address.ip4addr.s_addr = if_sa->sin_addr.s_addr; 532 1.1 kefren 533 1.17 kefren /* Put it on the wire */ 534 1.17 kefren sb = sendto(ip4socket, v, IPV4_HELLO_MSG_SIZE, 0, 535 1.17 kefren (struct sockaddr *) & sadest, sizeof(sadest)); 536 1.12 kefren if (sb < (ssize_t)(IPV4_HELLO_MSG_SIZE)) 537 1.1 kefren fatalp("send: %s", strerror(errno)); 538 1.1 kefren else 539 1.17 kefren debugp("Sent (IPv4) %zd bytes on %s" 540 1.17 kefren " (PDU: %d, Hello TLV: %d, CH: %d, TR: %d)\n", 541 1.12 kefren sb, ifb->ifa_name, 542 1.12 kefren ntohs(spdu->length), ntohs(t->length), 543 1.12 kefren ntohs(cht->length), ntohs(trtlv->length)); 544 1.12 kefren } 545 1.12 kefren #ifdef INET6 546 1.12 kefren /* Adjust lengths */ 547 1.12 kefren spdu->length = htons(IPV6_HELLO_MSG_SIZE - PDU_VER_LENGTH); 548 1.12 kefren t->length = htons(MSGID_SIZE + 549 1.12 kefren sizeof(struct common_hello_tlv) + 550 1.12 kefren IPV6_HELLO_MSG_SIZE - BASIC_HELLO_MSG_SIZE); 551 1.12 kefren trtlv->length = htons(sizeof(struct in6_addr)); 552 1.12 kefren trtlv->type = htons(TLV_IPV6_TRANSPORT); 553 1.12 kefren 554 1.12 kefren /* Prepare destination sockaddr */ 555 1.12 kefren memset(&sadest6, 0, sizeof(sadest6)); 556 1.12 kefren sadest6.sin6_len = sizeof(sadest6); 557 1.12 kefren sadest6.sin6_family = AF_INET6; 558 1.12 kefren sadest6.sin6_port = htons(LDP_PORT); 559 1.19 kefren sadest6.sin6_addr = in6addr_linklocal_allrouters; 560 1.12 kefren 561 1.17 kefren SLIST_FOREACH(hs, &hello_socket_head, listentry) 562 1.17 kefren if (hs->type == AF_INET6) { 563 1.17 kefren ip6socket = hs->socket; 564 1.17 kefren break; 565 1.17 kefren } 566 1.17 kefren 567 1.17 kefren lastifindex = UINT_MAX; 568 1.12 kefren for (ifb = ifa; ifb; ifb = ifb->ifa_next) { 569 1.17 kefren struct sockaddr_in6 * if_sa6 = 570 1.17 kefren (struct sockaddr_in6 *) ifb->ifa_addr; 571 1.17 kefren if (if_sa6->sin6_family != AF_INET6 || 572 1.17 kefren (!(ifb->ifa_flags & IFF_UP)) || 573 1.20 kefren (!(ifb->ifa_flags & IFF_MULTICAST)) || 574 1.17 kefren (ifb->ifa_flags & IFF_LOOPBACK) || 575 1.20 kefren is_passive_if(ifb->ifa_name) || 576 1.17 kefren IN6_IS_ADDR_LOOPBACK(&if_sa6->sin6_addr)) 577 1.12 kefren continue; 578 1.15 kefren /* 579 1.15 kefren * draft-ietf-mpls-ldp-ipv6-07 Section 5.1: 580 1.15 kefren * Additionally, the link-local 581 1.15 kefren * IPv6 address MUST be used as the source IP address in IPv6 582 1.15 kefren * LDP Link Hellos. 583 1.15 kefren */ 584 1.15 kefren if (IN6_IS_ADDR_LINKLOCAL(&if_sa6->sin6_addr) == 0) 585 1.15 kefren continue; 586 1.17 kefren /* We should have only one LLADDR per interface, but... */ 587 1.17 kefren if (lastifindex == if_nametoindex(ifb->ifa_name)) 588 1.17 kefren continue; 589 1.17 kefren lastifindex = if_nametoindex(ifb->ifa_name); 590 1.12 kefren 591 1.17 kefren if (setsockopt(ip6socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, 592 1.17 kefren &lastifindex, sizeof(int)) == -1) { 593 1.17 kefren fatalp("ssopt6 IPV6_MULTICAST_IF failed: %s for %s\n", 594 1.17 kefren strerror(errno), ifb->ifa_name); 595 1.12 kefren continue; 596 1.12 kefren } 597 1.17 kefren 598 1.12 kefren memcpy(&trtlv->address.ip6addr, &if_sa6->sin6_addr, 599 1.12 kefren sizeof(struct in6_addr)); 600 1.12 kefren 601 1.12 kefren /* Put it on the wire */ 602 1.17 kefren sb = sendto(ip6socket, v, IPV6_HELLO_MSG_SIZE, 603 1.12 kefren 0, (struct sockaddr *)&sadest6, sizeof(sadest6)); 604 1.12 kefren if (sb < (ssize_t)(IPV6_HELLO_MSG_SIZE)) 605 1.17 kefren fatalp("send6: %s", strerror(errno)); 606 1.12 kefren else 607 1.17 kefren debugp("Sent (IPv6) %zd bytes on %s " 608 1.12 kefren "(PDU: %d, Hello TLV: %d, CH: %d TR: %d)\n", 609 1.17 kefren sb, ifb->ifa_name, htons(spdu->length), 610 1.17 kefren htons(t->length), htons(cht->length), 611 1.17 kefren htons(trtlv->length)); 612 1.1 kefren } 613 1.12 kefren #endif 614 1.1 kefren freeifaddrs(ifa); 615 1.1 kefren free(v); 616 1.1 kefren } 617 1.1 kefren 618 1.1 kefren int 619 1.1 kefren get_message_id(void) 620 1.1 kefren { 621 1.1 kefren current_msg_id++; 622 1.1 kefren return current_msg_id; 623 1.1 kefren } 624 1.1 kefren 625 1.1 kefren static int 626 1.1 kefren get_local_addr(struct sockaddr_dl *sdl, struct in_addr *sin) 627 1.1 kefren { 628 1.1 kefren struct ifaddrs *ifa, *ifb; 629 1.1 kefren struct sockaddr_in *sinet; 630 1.1 kefren 631 1.1 kefren if (sdl == NULL) 632 1.1 kefren return -1; 633 1.1 kefren 634 1.1 kefren if (getifaddrs(&ifa) == -1) 635 1.1 kefren return -1; 636 1.1 kefren for (ifb = ifa; ifb; ifb = ifb->ifa_next) 637 1.1 kefren if (ifb->ifa_addr->sa_family == AF_INET) { 638 1.1 kefren if (if_nametoindex(ifb->ifa_name) != sdl->sdl_index) 639 1.1 kefren continue; 640 1.1 kefren sinet = (struct sockaddr_in*) ifb->ifa_addr; 641 1.1 kefren sin->s_addr = sinet->sin_addr.s_addr; 642 1.1 kefren freeifaddrs(ifa); 643 1.1 kefren return 0; 644 1.1 kefren } 645 1.1 kefren freeifaddrs(ifa); 646 1.1 kefren return -1; 647 1.1 kefren } 648 1.1 kefren 649 1.1 kefren /* Receive PDUs on Multicast UDP socket */ 650 1.1 kefren void 651 1.1 kefren recv_pdu(int sock) 652 1.1 kefren { 653 1.1 kefren struct ldp_pdu rpdu; 654 1.1 kefren int c, i; 655 1.1 kefren struct msghdr msg; 656 1.1 kefren struct iovec iov[1]; 657 1.1 kefren unsigned char recvspace[MAX_PDU_SIZE]; 658 1.1 kefren struct hello_tlv *t; 659 1.17 kefren union sockunion sender; 660 1.1 kefren struct sockaddr_dl *sdl = NULL; 661 1.1 kefren struct in_addr my_ldp_addr, local_addr; 662 1.1 kefren struct cmsghdr *cmptr; 663 1.1 kefren union { 664 1.1 kefren struct cmsghdr cm; 665 1.1 kefren char control[1024]; 666 1.1 kefren } control_un; 667 1.1 kefren 668 1.1 kefren memset(&msg, 0, sizeof(msg)); 669 1.1 kefren msg.msg_control = control_un.control; 670 1.1 kefren msg.msg_controllen = sizeof(control_un.control); 671 1.1 kefren msg.msg_flags = 0; 672 1.17 kefren msg.msg_name = &sender; 673 1.17 kefren msg.msg_namelen = sizeof(sender); 674 1.1 kefren iov[0].iov_base = recvspace; 675 1.1 kefren iov[0].iov_len = sizeof(recvspace); 676 1.1 kefren msg.msg_iov = iov; 677 1.1 kefren msg.msg_iovlen = 1; 678 1.1 kefren 679 1.1 kefren c = recvmsg(sock, &msg, MSG_WAITALL); 680 1.1 kefren 681 1.1 kefren /* Check to see if this is larger than MIN_PDU_SIZE */ 682 1.1 kefren if (c < MIN_PDU_SIZE) 683 1.1 kefren return; 684 1.1 kefren 685 1.1 kefren /* Read the PDU */ 686 1.1 kefren i = get_pdu(recvspace, &rpdu); 687 1.1 kefren 688 1.17 kefren debugp("recv_pdu(%d): PDU(size: %d) from: %s\n", sock, 689 1.17 kefren c, satos(&sender.sa)); 690 1.17 kefren 691 1.1 kefren /* We currently understand Version 1 */ 692 1.1 kefren if (rpdu.version != LDP_VERSION) { 693 1.17 kefren warnp("recv_pdu: Version mismatch\n"); 694 1.1 kefren return; 695 1.1 kefren } 696 1.1 kefren 697 1.17 kefren /* Check if it's our hello */ 698 1.1 kefren inet_aton(LDP_ID, &my_ldp_addr); 699 1.1 kefren if (rpdu.ldp_id.s_addr == my_ldp_addr.s_addr) { 700 1.17 kefren /* It should not be looped. We set MULTICAST_LOOP 0 */ 701 1.17 kefren fatalp("Received our PDU. Ignoring it\n"); 702 1.1 kefren return; 703 1.1 kefren } 704 1.1 kefren 705 1.1 kefren if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) || 706 1.1 kefren (msg.msg_flags & MSG_CTRUNC)) 707 1.1 kefren local_addr.s_addr = my_ldp_addr.s_addr; 708 1.1 kefren else { 709 1.1 kefren for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL; 710 1.1 kefren cmptr = CMSG_NXTHDR(&msg, cmptr)) 711 1.1 kefren if (cmptr->cmsg_level == IPPROTO_IP && 712 1.1 kefren cmptr->cmsg_type == IP_RECVIF) { 713 1.1 kefren sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr); 714 1.1 kefren break; 715 1.1 kefren } 716 1.1 kefren if (get_local_addr(sdl, &local_addr) != 0) 717 1.1 kefren local_addr.s_addr = my_ldp_addr.s_addr; 718 1.1 kefren } 719 1.1 kefren 720 1.1 kefren 721 1.1 kefren debugp("Read %d bytes from address %s Length: %.4d Version: %d\n", 722 1.1 kefren c, inet_ntoa(rpdu.ldp_id), rpdu.length, rpdu.version); 723 1.1 kefren 724 1.1 kefren /* Fill the TLV messages */ 725 1.1 kefren t = get_hello_tlv(recvspace + i, c - i); 726 1.24 kefren run_ldp_hello(&rpdu, t, &sender.sa, &local_addr, sock, may_connect); 727 1.1 kefren } 728 1.1 kefren 729 1.1 kefren void 730 1.1 kefren send_hello_alarm(int unused) 731 1.1 kefren { 732 1.4 kefren struct ldp_peer *p, *ptmp; 733 1.3 kefren struct hello_info *hi, *hinext; 734 1.1 kefren time_t t = time(NULL); 735 1.1 kefren int olderrno = errno; 736 1.1 kefren 737 1.24 kefren if (may_connect == false) 738 1.24 kefren may_connect = true; 739 1.1 kefren /* Send hellos */ 740 1.1 kefren if (!(t % ldp_hello_time)) 741 1.1 kefren send_hello(); 742 1.1 kefren 743 1.1 kefren /* Timeout -- */ 744 1.1 kefren SLIST_FOREACH(p, &ldp_peer_head, peers) 745 1.1 kefren p->timeout--; 746 1.1 kefren 747 1.1 kefren /* Check for timeout */ 748 1.4 kefren SLIST_FOREACH_SAFE(p, &ldp_peer_head, peers, ptmp) 749 1.1 kefren if (p->timeout < 1) 750 1.1 kefren switch (p->state) { 751 1.1 kefren case LDP_PEER_HOLDDOWN: 752 1.1 kefren debugp("LDP holddown expired for peer %s\n", 753 1.1 kefren inet_ntoa(p->ldp_id)); 754 1.1 kefren ldp_peer_delete(p); 755 1.4 kefren break; 756 1.1 kefren case LDP_PEER_ESTABLISHED: 757 1.1 kefren case LDP_PEER_CONNECTED: 758 1.1 kefren send_notification(p, 0, 759 1.23 kefren NOTIF_FATAL|NOTIF_KEEP_ALIVE_TIMER_EXPIRED); 760 1.1 kefren warnp("Keepalive expired for %s\n", 761 1.1 kefren inet_ntoa(p->ldp_id)); 762 1.1 kefren ldp_peer_holddown(p); 763 1.1 kefren break; 764 1.1 kefren } /* switch */ 765 1.1 kefren 766 1.1 kefren /* send keepalives */ 767 1.3 kefren if (!(t % ldp_keepalive_time)) { 768 1.1 kefren SLIST_FOREACH(p, &ldp_peer_head, peers) 769 1.1 kefren if (p->state == LDP_PEER_ESTABLISHED) { 770 1.1 kefren debugp("Sending KeepAlive to %s\n", 771 1.1 kefren inet_ntoa(p->ldp_id)); 772 1.1 kefren keep_alive(p); 773 1.1 kefren } 774 1.1 kefren } 775 1.1 kefren 776 1.21 kefren /* Decrement and Check hello keepalives */ 777 1.21 kefren SLIST_FOREACH_SAFE(hi, &hello_info_head, infos, hinext) { 778 1.10 kefren if (hi->keepalive != 0xFFFF) 779 1.10 kefren hi->keepalive--; 780 1.3 kefren if (hi->keepalive < 1) 781 1.1 kefren SLIST_REMOVE(&hello_info_head, hi, hello_info, infos); 782 1.21 kefren } 783 1.1 kefren 784 1.1 kefren /* Set the alarm again and bail out */ 785 1.1 kefren alarm(1); 786 1.1 kefren errno = olderrno; 787 1.1 kefren } 788 1.1 kefren 789 1.11 joerg static void 790 1.1 kefren bail_out(int x) 791 1.1 kefren { 792 1.1 kefren ldp_peer_holddown_all(); 793 1.1 kefren flush_mpls_routes(); 794 1.1 kefren exit(0); 795 1.1 kefren } 796 1.1 kefren 797 1.29 kefren static void 798 1.29 kefren print_info(int x) 799 1.29 kefren { 800 1.29 kefren printf("Info for %s\n-------\n", LDP_ID); 801 1.29 kefren printf("Neighbours:\n"); 802 1.29 kefren show_neighbours(1, NULL); 803 1.29 kefren printf("Bindings:\n"); 804 1.29 kefren show_bindings(1, NULL); 805 1.29 kefren printf("Labels:\n"); 806 1.29 kefren show_labels(1, NULL); 807 1.29 kefren printf("--------\n"); 808 1.29 kefren } 809 1.29 kefren 810 1.1 kefren /* 811 1.1 kefren * The big poll that catches every single event 812 1.1 kefren * on every socket. 813 1.1 kefren */ 814 1.7 kefren int 815 1.1 kefren the_big_loop(void) 816 1.1 kefren { 817 1.1 kefren int sock_error; 818 1.1 kefren uint32_t i; 819 1.1 kefren socklen_t sock_error_size = sizeof(int); 820 1.1 kefren struct ldp_peer *p; 821 1.1 kefren struct com_sock *cs; 822 1.1 kefren struct pollfd pfd[MAX_POLL_FDS]; 823 1.17 kefren struct hello_socket *hs; 824 1.17 kefren nfds_t pollsum; 825 1.34 roy #ifdef RO_MSGFILTER 826 1.34 roy unsigned char msgfilter[] = { 827 1.34 roy RTM_NEWADDR, RTM_DELADDR, 828 1.34 roy RTM_ADD, RTM_DELETE, RTM_CHANGE, 829 1.34 roy }; 830 1.34 roy #endif 831 1.1 kefren 832 1.17 kefren assert(MAX_POLL_FDS > 5); 833 1.7 kefren 834 1.1 kefren SLIST_INIT(&hello_info_head); 835 1.1 kefren 836 1.1 kefren signal(SIGALRM, send_hello_alarm); 837 1.1 kefren signal(SIGPIPE, SIG_IGN); 838 1.10 kefren signal(SIGINT, bail_out); 839 1.1 kefren signal(SIGTERM, bail_out); 840 1.29 kefren signal(SIGINFO, print_info); 841 1.17 kefren 842 1.17 kefren /* Send first hellos in 5 seconds. Avoid No hello notifications */ 843 1.24 kefren may_connect = false; 844 1.17 kefren alarm(5); 845 1.1 kefren 846 1.1 kefren route_socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); 847 1.29 kefren setsockopt(route_socket, SOL_SOCKET, SO_USELOOPBACK, &(int){0}, 848 1.29 kefren sizeof(int)); 849 1.34 roy #ifdef RO_MSGFILTER 850 1.34 roy setsockopt(route_socket, PF_ROUTE, RO_MSGFILTER, &msgfilter, 851 1.34 roy sizeof(msgfilter)); 852 1.34 roy #endif 853 1.1 kefren 854 1.7 kefren sock_error = bind_current_routes(); 855 1.7 kefren if (sock_error != LDP_E_OK) { 856 1.1 kefren fatalp("Cannot get current routes\n"); 857 1.7 kefren return sock_error; 858 1.7 kefren } 859 1.1 kefren 860 1.1 kefren for (;;) { 861 1.1 kefren pfd[0].fd = ls; 862 1.1 kefren pfd[0].events = POLLRDNORM; 863 1.1 kefren pfd[0].revents = 0; 864 1.1 kefren 865 1.1 kefren pfd[1].fd = route_socket; 866 1.1 kefren pfd[1].events = POLLRDNORM; 867 1.1 kefren pfd[1].revents = 0; 868 1.1 kefren 869 1.1 kefren pfd[2].fd = command_socket; 870 1.1 kefren pfd[2].events = POLLRDNORM; 871 1.1 kefren pfd[2].revents = 0; 872 1.1 kefren 873 1.17 kefren /* Hello sockets */ 874 1.17 kefren pollsum = 3; 875 1.17 kefren SLIST_FOREACH(hs, &hello_socket_head, listentry) { 876 1.17 kefren pfd[pollsum].fd = hs->socket; 877 1.17 kefren pfd[pollsum].events = POLLIN; 878 1.17 kefren pfd[pollsum].revents = 0; 879 1.17 kefren pollsum++; 880 1.17 kefren } 881 1.1 kefren 882 1.1 kefren /* Command sockets */ 883 1.1 kefren for (i=0; i < MAX_COMMAND_SOCKETS; i++) 884 1.1 kefren if (csockets[i].socket != -1) { 885 1.7 kefren if (pollsum >= MAX_POLL_FDS) 886 1.7 kefren break; 887 1.1 kefren pfd[pollsum].fd = csockets[i].socket; 888 1.1 kefren pfd[pollsum].events = POLLIN; 889 1.1 kefren pfd[pollsum].revents = 0; 890 1.1 kefren pollsum++; 891 1.1 kefren } 892 1.1 kefren 893 1.1 kefren /* LDP Peer sockets */ 894 1.1 kefren SLIST_FOREACH(p, &ldp_peer_head, peers) { 895 1.1 kefren if (p->socket < 1) 896 1.1 kefren continue; 897 1.1 kefren switch (p->state) { 898 1.1 kefren case LDP_PEER_CONNECTED: 899 1.1 kefren case LDP_PEER_ESTABLISHED: 900 1.7 kefren if (pollsum >= MAX_POLL_FDS) 901 1.7 kefren break; 902 1.1 kefren pfd[pollsum].fd = p->socket; 903 1.1 kefren pfd[pollsum].events = POLLRDNORM; 904 1.1 kefren pfd[pollsum].revents = 0; 905 1.1 kefren pollsum++; 906 1.1 kefren break; 907 1.1 kefren case LDP_PEER_CONNECTING: 908 1.7 kefren if (pollsum >= MAX_POLL_FDS) 909 1.7 kefren break; 910 1.1 kefren pfd[pollsum].fd = p->socket; 911 1.1 kefren pfd[pollsum].events = POLLWRNORM; 912 1.1 kefren pfd[pollsum].revents = 0; 913 1.1 kefren pollsum++; 914 1.1 kefren break; 915 1.1 kefren } 916 1.1 kefren } 917 1.1 kefren 918 1.1 kefren if (pollsum >= MAX_POLL_FDS) { 919 1.1 kefren fatalp("Too many sockets. Increase MAX_POLL_FDS\n"); 920 1.7 kefren return LDP_E_TOO_MANY_FDS; 921 1.8 kefren } 922 1.1 kefren if (poll(pfd, pollsum, INFTIM) < 0) { 923 1.1 kefren if (errno != EINTR) 924 1.1 kefren fatalp("poll: %s", strerror(errno)); 925 1.1 kefren continue; 926 1.8 kefren } 927 1.1 kefren 928 1.1 kefren for (i = 0; i < pollsum; i++) { 929 1.1 kefren if ((pfd[i].revents & POLLRDNORM) || 930 1.1 kefren (pfd[i].revents & POLLIN)) { 931 1.8 kefren if(pfd[i].fd == ls) 932 1.1 kefren new_peer_connection(); 933 1.8 kefren else if (pfd[i].fd == route_socket) { 934 1.1 kefren struct rt_msg xbuf; 935 1.31 kefren int l, rtmlen = sizeof(xbuf); 936 1.31 kefren /* Read at least rtm_msglen */ 937 1.31 kefren l = recv(route_socket, &xbuf, 938 1.31 kefren sizeof(u_short), MSG_PEEK); 939 1.31 kefren if (l == sizeof(u_short)) 940 1.31 kefren rtmlen = xbuf.m_rtm.rtm_msglen; 941 1.1 kefren do { 942 1.31 kefren l = recv(route_socket, &xbuf, 943 1.31 kefren rtmlen, MSG_WAITALL); 944 1.1 kefren } while ((l == -1) && (errno == EINTR)); 945 1.1 kefren 946 1.1 kefren if (l == -1) 947 1.1 kefren break; 948 1.1 kefren 949 1.8 kefren check_route(&xbuf, l); 950 1.1 kefren 951 1.17 kefren } else if (is_hello_socket(pfd[i].fd) == 1) { 952 1.1 kefren /* Receiving hello socket */ 953 1.1 kefren recv_pdu(pfd[i].fd); 954 1.1 kefren } else if (pfd[i].fd == command_socket) { 955 1.1 kefren command_accept(command_socket); 956 1.1 kefren } else if ((cs = is_command_socket(pfd[i].fd)) 957 1.1 kefren != NULL) { 958 1.1 kefren command_dispatch(cs); 959 1.1 kefren } else { 960 1.1 kefren /* ldp peer socket */ 961 1.1 kefren p = get_ldp_peer_by_socket(pfd[i].fd); 962 1.1 kefren if (p) 963 1.1 kefren recv_session_pdu(p); 964 1.1 kefren } 965 1.1 kefren } else if(pfd[i].revents & POLLWRNORM) { 966 1.1 kefren p = get_ldp_peer_by_socket(pfd[i].fd); 967 1.1 kefren if (!p) 968 1.1 kefren continue; 969 1.30 kefren assert(p->state == LDP_PEER_CONNECTING); 970 1.9 kefren if (getsockopt(pfd[i].fd, SOL_SOCKET, SO_ERROR, 971 1.9 kefren &sock_error, &sock_error_size) != 0 || 972 1.9 kefren sock_error != 0) { 973 1.9 kefren ldp_peer_holddown(p); 974 1.9 kefren sock_error = 0; 975 1.9 kefren } else { 976 1.9 kefren p->state = LDP_PEER_CONNECTED; 977 1.9 kefren send_initialize(p); 978 1.1 kefren } 979 1.1 kefren } 980 1.1 kefren } 981 1.1 kefren 982 1.1 kefren for (int ri = 0; ri < replay_index; ri++) { 983 1.1 kefren debugp("Replaying: PID %d, SEQ %d\n", 984 1.1 kefren replay_rt[ri].m_rtm.rtm_pid, 985 1.1 kefren replay_rt[ri].m_rtm.rtm_seq); 986 1.1 kefren check_route(&replay_rt[ri], sizeof(struct rt_msg)); 987 1.1 kefren } 988 1.1 kefren replay_index = 0; 989 1.1 kefren } /* for (;;) */ 990 1.1 kefren } 991 1.1 kefren 992 1.1 kefren void 993 1.1 kefren new_peer_connection() 994 1.1 kefren { 995 1.25 kefren union sockunion peer_address, my_address; 996 1.25 kefren struct in_addr *peer_ldp_id = NULL; 997 1.25 kefren struct hello_info *hi; 998 1.28 kefren int s; 999 1.1 kefren 1000 1.25 kefren s = accept(ls, &peer_address.sa, 1001 1.25 kefren & (socklen_t) { sizeof(union sockunion) } ); 1002 1.1 kefren if (s < 0) { 1003 1.1 kefren fatalp("accept: %s", strerror(errno)); 1004 1.1 kefren return; 1005 1.1 kefren } 1006 1.1 kefren 1007 1.25 kefren if (getsockname(s, &my_address.sa, 1008 1.25 kefren & (socklen_t) { sizeof(union sockunion) } )) { 1009 1.1 kefren fatalp("new_peer_connection(): cannot getsockname\n"); 1010 1.1 kefren close(s); 1011 1.1 kefren return; 1012 1.1 kefren } 1013 1.26 kefren 1014 1.25 kefren if (peer_address.sa.sa_family == AF_INET) 1015 1.25 kefren peer_address.sin.sin_port = 0; 1016 1.25 kefren else if (peer_address.sa.sa_family == AF_INET6) 1017 1.25 kefren peer_address.sin6.sin6_port = 0; 1018 1.25 kefren else { 1019 1.25 kefren fatalp("Unknown peer address family\n"); 1020 1.25 kefren close(s); 1021 1.25 kefren return; 1022 1.25 kefren } 1023 1.1 kefren 1024 1.26 kefren /* Already peered or in holddown ? */ 1025 1.26 kefren if (get_ldp_peer(&peer_address.sa) != NULL) { 1026 1.26 kefren close(s); 1027 1.26 kefren return; 1028 1.26 kefren } 1029 1.26 kefren 1030 1.26 kefren warnp("Accepted a connection from %s\n", satos(&peer_address.sa)); 1031 1.26 kefren 1032 1.25 kefren /* Verify if it should connect - XXX: no check for INET6 */ 1033 1.25 kefren if (peer_address.sa.sa_family == AF_INET && 1034 1.25 kefren ntohl(peer_address.sin.sin_addr.s_addr) < 1035 1.25 kefren ntohl(my_address.sin.sin_addr.s_addr)) { 1036 1.1 kefren fatalp("Peer %s: connect from lower ID\n", 1037 1.25 kefren satos(&peer_address.sa)); 1038 1.1 kefren close(s); 1039 1.1 kefren return; 1040 1.1 kefren } 1041 1.25 kefren 1042 1.25 kefren /* Match hello info in order to get ldp_id */ 1043 1.25 kefren SLIST_FOREACH(hi, &hello_info_head, infos) { 1044 1.25 kefren if (sockaddr_cmp(&peer_address.sa, 1045 1.25 kefren &hi->transport_address.sa) == 0) { 1046 1.25 kefren peer_ldp_id = &hi->ldp_id; 1047 1.25 kefren break; 1048 1.25 kefren } 1049 1.25 kefren } 1050 1.25 kefren if (peer_ldp_id == NULL) { 1051 1.29 kefren warnp("Got connection from %s, but no hello info exists\n", 1052 1.25 kefren satos(&peer_address.sa)); 1053 1.25 kefren close(s); 1054 1.25 kefren return; 1055 1.25 kefren } else 1056 1.25 kefren ldp_peer_new(peer_ldp_id, &peer_address.sa, NULL, 1057 1.25 kefren ldp_holddown_time, s); 1058 1.1 kefren 1059 1.1 kefren } 1060 1.1 kefren 1061 1.1 kefren void 1062 1.28 kefren send_initialize(const struct ldp_peer * p) 1063 1.1 kefren { 1064 1.1 kefren struct init_tlv ti; 1065 1.1 kefren 1066 1.1 kefren ti.type = htons(LDP_INITIALIZE); 1067 1.1 kefren ti.length = htons(sizeof(struct init_tlv) - TLV_TYPE_LENGTH); 1068 1.1 kefren ti.messageid = htonl(get_message_id()); 1069 1.1 kefren ti.cs_type = htons(TLV_COMMON_SESSION); 1070 1.1 kefren ti.cs_len = htons(CS_LEN); 1071 1.1 kefren ti.cs_version = htons(LDP_VERSION); 1072 1.3 kefren ti.cs_keepalive = htons(2 * ldp_keepalive_time); 1073 1.1 kefren ti.cs_adpvlim = 0; 1074 1.1 kefren ti.cs_maxpdulen = htons(MAX_PDU_SIZE); 1075 1.1 kefren ti.cs_peeraddress.s_addr = p->ldp_id.s_addr; 1076 1.1 kefren ti.cs_peeraddrspace = 0; 1077 1.1 kefren 1078 1.1 kefren send_tlv(p, (struct tlv *) (void *) &ti); 1079 1.1 kefren } 1080 1.1 kefren 1081 1.1 kefren void 1082 1.28 kefren keep_alive(const struct ldp_peer * p) 1083 1.1 kefren { 1084 1.1 kefren struct ka_tlv kt; 1085 1.1 kefren 1086 1.1 kefren kt.type = htons(LDP_KEEPALIVE); 1087 1.1 kefren kt.length = htons(sizeof(kt.messageid)); 1088 1.1 kefren kt.messageid = htonl(get_message_id()); 1089 1.1 kefren 1090 1.1 kefren send_tlv(p, (struct tlv *) (void *) &kt); 1091 1.1 kefren } 1092 1.1 kefren 1093 1.29 kefren /* 1094 1.29 kefren * Process a message received from a peer 1095 1.29 kefren */ 1096 1.29 kefren void 1097 1.1 kefren recv_session_pdu(struct ldp_peer * p) 1098 1.1 kefren { 1099 1.1 kefren struct ldp_pdu *rpdu; 1100 1.1 kefren struct address_tlv *atlv; 1101 1.1 kefren struct al_tlv *altlv; 1102 1.1 kefren struct init_tlv *itlv; 1103 1.1 kefren struct label_map_tlv *lmtlv; 1104 1.1 kefren struct fec_tlv *fectlv; 1105 1.6 joerg struct label_tlv *labeltlv; 1106 1.1 kefren struct notification_tlv *nottlv; 1107 1.1 kefren struct hello_info *hi; 1108 1.1 kefren 1109 1.1 kefren int c; 1110 1.1 kefren int32_t wo = 0; 1111 1.1 kefren struct tlv *ttmp; 1112 1.1 kefren unsigned char recvspace[MAX_PDU_SIZE]; 1113 1.1 kefren 1114 1.1 kefren memset(recvspace, 0, MAX_PDU_SIZE); 1115 1.1 kefren 1116 1.30 kefren do { 1117 1.30 kefren c = recv(p->socket, (void *) recvspace, MAX_PDU_SIZE, MSG_PEEK); 1118 1.30 kefren } while (c == -1 && errno == EINTR); 1119 1.1 kefren 1120 1.1 kefren debugp("Ready to read %d bytes\n", c); 1121 1.1 kefren 1122 1.1 kefren if (c < 1) { /* Session closed */ 1123 1.1 kefren warnp("Error in connection with %s\n", inet_ntoa(p->ldp_id)); 1124 1.1 kefren ldp_peer_holddown(p); 1125 1.1 kefren return; 1126 1.1 kefren } 1127 1.1 kefren if (c > MAX_PDU_SIZE) { 1128 1.1 kefren debugp("Incoming PDU size exceeds MAX_PDU_SIZE !\n"); 1129 1.1 kefren return; 1130 1.1 kefren } 1131 1.1 kefren if (c < MIN_PDU_SIZE) { 1132 1.28 kefren debugp("PDU too small received from peer %s\n", 1133 1.28 kefren inet_ntoa(p->ldp_id)); 1134 1.1 kefren return; 1135 1.1 kefren } 1136 1.1 kefren rpdu = (struct ldp_pdu *) recvspace; 1137 1.30 kefren do { 1138 1.30 kefren c = recv(p->socket, (void *) recvspace, 1139 1.30 kefren ntohs(rpdu->length) + PDU_VER_LENGTH, MSG_WAITALL); 1140 1.30 kefren } while (c == -1 && errno == EINTR); 1141 1.1 kefren 1142 1.30 kefren /* sanity check */ 1143 1.1 kefren if (check_recv_pdu(p, rpdu, c) != 0) 1144 1.1 kefren return; 1145 1.1 kefren 1146 1.1 kefren debugp("Read %d bytes, PDU size: %d bytes\n", c, ntohs(rpdu->length)); 1147 1.1 kefren wo = sizeof(struct ldp_pdu); 1148 1.1 kefren 1149 1.1 kefren while (wo + TLV_TYPE_LENGTH < (uint)c) { 1150 1.1 kefren 1151 1.1 kefren ttmp = (struct tlv *) (&recvspace[wo]); 1152 1.1 kefren 1153 1.1 kefren if ((ntohs(ttmp->type) != LDP_KEEPALIVE) && 1154 1.1 kefren (ntohs(ttmp->type) != LDP_LABEL_MAPPING)) { 1155 1.1 kefren debugp("Got Type: 0x%.4X (Length: %d) from %s\n", 1156 1.1 kefren ntohs(ttmp->type), ntohs(ttmp->length), 1157 1.1 kefren inet_ntoa(p->ldp_id)); 1158 1.1 kefren } else 1159 1.1 kefren debugp("Got Type: 0x%.4X (Length: %d) from %s\n", 1160 1.1 kefren ntohs(ttmp->type), ntohs(ttmp->length), 1161 1.1 kefren inet_ntoa(p->ldp_id)); 1162 1.1 kefren 1163 1.1 kefren /* Should we get the message ? */ 1164 1.1 kefren if (p->state != LDP_PEER_ESTABLISHED && 1165 1.1 kefren ntohs(ttmp->type) != LDP_INITIALIZE && 1166 1.22 kefren ntohs(ttmp->type) != LDP_KEEPALIVE && 1167 1.22 kefren ntohs(ttmp->type) != LDP_NOTIFICATION) 1168 1.1 kefren break; 1169 1.1 kefren /* The big switch */ 1170 1.1 kefren switch (ntohs(ttmp->type)) { 1171 1.1 kefren case LDP_INITIALIZE: 1172 1.1 kefren itlv = (struct init_tlv *)ttmp; 1173 1.1 kefren /* Check size */ 1174 1.1 kefren if (ntohs(itlv->length) < 1175 1.1 kefren sizeof(struct init_tlv) - TLV_TYPE_LENGTH) { 1176 1.17 kefren debugp("Bad size\n"); 1177 1.1 kefren send_notification(p, 0, 1178 1.1 kefren NOTIF_BAD_PDU_LEN | NOTIF_FATAL); 1179 1.1 kefren ldp_peer_holddown(p); 1180 1.1 kefren break; 1181 1.1 kefren } 1182 1.1 kefren /* Check version */ 1183 1.1 kefren if (ntohs(itlv->cs_version) != LDP_VERSION) { 1184 1.17 kefren debugp("Bad version"); 1185 1.1 kefren send_notification(p, ntohl(itlv->messageid), 1186 1.1 kefren NOTIF_BAD_LDP_VER | NOTIF_FATAL); 1187 1.1 kefren ldp_peer_holddown(p); 1188 1.1 kefren break; 1189 1.1 kefren } 1190 1.1 kefren /* Check if we got any hello from this one */ 1191 1.1 kefren SLIST_FOREACH(hi, &hello_info_head, infos) 1192 1.1 kefren if (hi->ldp_id.s_addr == rpdu->ldp_id.s_addr) 1193 1.1 kefren break; 1194 1.1 kefren if (hi == NULL) { 1195 1.17 kefren debugp("No hello. Moving peer to holddown\n"); 1196 1.1 kefren send_notification(p, ntohl(itlv->messageid), 1197 1.1 kefren NOTIF_SESSION_REJECTED_NO_HELLO | NOTIF_FATAL); 1198 1.1 kefren ldp_peer_holddown(p); 1199 1.1 kefren break; 1200 1.1 kefren } 1201 1.1 kefren 1202 1.1 kefren if (!p->master) { 1203 1.27 kefren send_initialize(p); 1204 1.1 kefren keep_alive(p); 1205 1.1 kefren } else { 1206 1.1 kefren p->state = LDP_PEER_ESTABLISHED; 1207 1.1 kefren p->established_t = time(NULL); 1208 1.1 kefren keep_alive(p); 1209 1.1 kefren 1210 1.1 kefren /* 1211 1.1 kefren * Recheck here ldp id because we accepted 1212 1.1 kefren * connection without knowing who is it for sure 1213 1.1 kefren */ 1214 1.1 kefren p->ldp_id.s_addr = rpdu->ldp_id.s_addr; 1215 1.1 kefren 1216 1.1 kefren fatalp("LDP neighbour %s is UP\n", 1217 1.1 kefren inet_ntoa(p->ldp_id)); 1218 1.1 kefren mpls_add_ldp_peer(p); 1219 1.1 kefren send_addresses(p); 1220 1.1 kefren send_all_bindings(p); 1221 1.1 kefren } 1222 1.1 kefren break; 1223 1.1 kefren case LDP_KEEPALIVE: 1224 1.1 kefren if ((p->state == LDP_PEER_CONNECTED) && (!p->master)) { 1225 1.1 kefren p->state = LDP_PEER_ESTABLISHED; 1226 1.1 kefren p->established_t = time(NULL); 1227 1.1 kefren fatalp("LDP neighbour %s is UP\n", 1228 1.1 kefren inet_ntoa(p->ldp_id)); 1229 1.1 kefren mpls_add_ldp_peer(p); 1230 1.1 kefren send_addresses(p); 1231 1.1 kefren send_all_bindings(p); 1232 1.1 kefren } 1233 1.1 kefren p->timeout = p->holdtime; 1234 1.1 kefren break; 1235 1.1 kefren case LDP_ADDRESS: 1236 1.1 kefren /* Add peer addresses */ 1237 1.1 kefren atlv = (struct address_tlv *) ttmp; 1238 1.1 kefren altlv = (struct al_tlv *) (&atlv[1]); 1239 1.1 kefren add_ifaddresses(p, altlv); 1240 1.29 kefren /* 1241 1.29 kefren * try to see if we have labels with null peer that 1242 1.29 kefren * would match the new peer 1243 1.29 kefren */ 1244 1.29 kefren label_check_assoc(p); 1245 1.1 kefren print_bounded_addresses(p); 1246 1.1 kefren break; 1247 1.1 kefren case LDP_ADDRESS_WITHDRAW: 1248 1.1 kefren atlv = (struct address_tlv *) ttmp; 1249 1.1 kefren altlv = (struct al_tlv *) (&atlv[1]); 1250 1.1 kefren del_ifaddresses(p, altlv); 1251 1.1 kefren break; 1252 1.1 kefren case LDP_LABEL_MAPPING: 1253 1.1 kefren lmtlv = (struct label_map_tlv *) ttmp; 1254 1.1 kefren fectlv = (struct fec_tlv *) (&lmtlv[1]); 1255 1.1 kefren labeltlv = (struct label_tlv *)((unsigned char *)fectlv 1256 1.1 kefren + ntohs(fectlv->length) + TLV_TYPE_LENGTH); 1257 1.1 kefren map_label(p, fectlv, labeltlv); 1258 1.1 kefren break; 1259 1.1 kefren case LDP_LABEL_REQUEST: 1260 1.1 kefren lmtlv = (struct label_map_tlv *) ttmp; 1261 1.1 kefren fectlv = (struct fec_tlv *) (&lmtlv[1]); 1262 1.1 kefren switch (request_respond(p, lmtlv, fectlv)) { 1263 1.1 kefren case LDP_E_BAD_FEC: 1264 1.1 kefren send_notification(p, ntohl(lmtlv->messageid), 1265 1.1 kefren NOTIF_UNKNOWN_TLV); 1266 1.1 kefren break; 1267 1.1 kefren case LDP_E_BAD_AF: 1268 1.1 kefren send_notification(p, ntohl(lmtlv->messageid), 1269 1.1 kefren NOTIF_UNSUPPORTED_AF); 1270 1.1 kefren break; 1271 1.1 kefren case LDP_E_NO_SUCH_ROUTE: 1272 1.1 kefren send_notification(p, ntohl(lmtlv->messageid), 1273 1.1 kefren NOTIF_NO_ROUTE); 1274 1.1 kefren break; 1275 1.1 kefren } 1276 1.1 kefren break; 1277 1.1 kefren case LDP_LABEL_WITHDRAW: 1278 1.1 kefren lmtlv = (struct label_map_tlv *) ttmp; 1279 1.1 kefren fectlv = (struct fec_tlv *) (&lmtlv[1]); 1280 1.1 kefren if (withdraw_label(p, fectlv) == LDP_E_OK) { 1281 1.1 kefren /* Send RELEASE */ 1282 1.1 kefren prepare_release(ttmp); 1283 1.1 kefren send_tlv(p, ttmp); 1284 1.1 kefren } 1285 1.1 kefren break; 1286 1.1 kefren case LDP_LABEL_RELEASE: 1287 1.1 kefren /* 1288 1.1 kefren * XXX: we need to make a timed queue... 1289 1.1 kefren * For now I just assume peers are processing messages 1290 1.1 kefren * correctly so I just ignore confirmations 1291 1.1 kefren */ 1292 1.1 kefren wo = -1; /* Ignore rest of message */ 1293 1.1 kefren break; 1294 1.1 kefren case LDP_LABEL_ABORT: 1295 1.1 kefren /* XXX: For now I pretend I can process everything 1296 1.12 kefren * RFC 5036, Section 3.5.9.1 1297 1.1 kefren * If an LSR receives a Label Abort Request Message after it 1298 1.1 kefren * has responded to the Label Request in question with a Label 1299 1.1 kefren * Mapping message or a Notification message, it ignores the 1300 1.1 kefren * abort request. 1301 1.1 kefren */ 1302 1.1 kefren wo = -1; 1303 1.1 kefren break; 1304 1.1 kefren case LDP_NOTIFICATION: 1305 1.1 kefren nottlv = (struct notification_tlv *) ttmp; 1306 1.1 kefren nottlv->st_code = ntohl(nottlv->st_code); 1307 1.1 kefren fatalp("Got notification 0x%X from peer %s\n", 1308 1.1 kefren nottlv->st_code, inet_ntoa(p->ldp_id)); 1309 1.1 kefren if (nottlv->st_code >> 31) { 1310 1.1 kefren fatalp("LDP peer %s signalized %s\n", 1311 1.1 kefren inet_ntoa(p->ldp_id), 1312 1.1 kefren NOTIF_STR[(nottlv->st_code << 1) >> 1]); 1313 1.1 kefren ldp_peer_holddown(p); 1314 1.1 kefren wo = -1; 1315 1.1 kefren } 1316 1.1 kefren break; 1317 1.1 kefren case LDP_HELLO: 1318 1.1 kefren /* No hellos should came on tcp session */ 1319 1.1 kefren wo = -1; 1320 1.1 kefren break; 1321 1.1 kefren default: 1322 1.1 kefren warnp("Unknown TLV received from %s\n", 1323 1.1 kefren inet_ntoa(p->ldp_id)); 1324 1.1 kefren debug_tlv(ttmp); 1325 1.1 kefren wo = -1;/* discard the rest of the message */ 1326 1.1 kefren break; 1327 1.1 kefren } 1328 1.1 kefren if (wo < 0) { 1329 1.1 kefren debugp("Discarding the rest of the message\n"); 1330 1.1 kefren break; 1331 1.1 kefren } else { 1332 1.1 kefren wo += ntohs(ttmp->length) + TLV_TYPE_LENGTH; 1333 1.1 kefren debugp("WORKED ON %u bytes (Left %d)\n", wo, c - wo); 1334 1.1 kefren } 1335 1.1 kefren } /* while */ 1336 1.1 kefren 1337 1.1 kefren } 1338 1.1 kefren 1339 1.1 kefren /* Sends a pdu, tlv pair to a connected peer */ 1340 1.1 kefren int 1341 1.28 kefren send_message(const struct ldp_peer * p, const struct ldp_pdu * pdu, 1342 1.28 kefren const struct tlv * t) 1343 1.1 kefren { 1344 1.1 kefren unsigned char sendspace[MAX_PDU_SIZE]; 1345 1.1 kefren 1346 1.1 kefren /* Check if peer is connected */ 1347 1.1 kefren switch (p->state) { 1348 1.1 kefren case LDP_PEER_CONNECTED: 1349 1.1 kefren case LDP_PEER_ESTABLISHED: 1350 1.1 kefren break; 1351 1.1 kefren default: 1352 1.1 kefren return -1; 1353 1.1 kefren } 1354 1.1 kefren 1355 1.1 kefren /* Check length validity first */ 1356 1.1 kefren if (ntohs(pdu->length) != 1357 1.1 kefren ntohs(t->length) + TLV_TYPE_LENGTH + PDU_PAYLOAD_LENGTH) { 1358 1.1 kefren fatalp("LDP: TLV - PDU incompability. Message discarded\n"); 1359 1.1 kefren fatalp("LDP: TLV len %d - PDU len %d\n", ntohs(t->length), 1360 1.1 kefren ntohs(pdu->length)); 1361 1.1 kefren return -1; 1362 1.1 kefren } 1363 1.1 kefren if (ntohs(t->length) + PDU_VER_LENGTH > MAX_PDU_SIZE) { 1364 1.1 kefren fatalp("Message to large discarded\n"); 1365 1.1 kefren return -1; 1366 1.1 kefren } 1367 1.1 kefren /* Arrange them in a buffer and send */ 1368 1.1 kefren memcpy(sendspace, pdu, sizeof(struct ldp_pdu)); 1369 1.1 kefren memcpy(sendspace + sizeof(struct ldp_pdu), t, 1370 1.1 kefren ntohs(t->length) + TLV_TYPE_LENGTH); 1371 1.1 kefren 1372 1.1 kefren /* Report keepalives only for DEBUG */ 1373 1.1 kefren if ((ntohs(t->type) != 0x201) && (ntohs(t->type) != 0x400)) { 1374 1.1 kefren debugp("Sending message type 0x%.4X to %s (size: %d)\n", 1375 1.1 kefren ntohs(t->type), inet_ntoa(p->ldp_id), ntohs(t->length)); 1376 1.1 kefren } else 1377 1.1 kefren /* downgraded from warnp to debugp for now */ 1378 1.1 kefren debugp("Sending message type 0x%.4X to %s (size: %d)\n", 1379 1.1 kefren ntohs(t->type), inet_ntoa(p->ldp_id), ntohs(t->length)); 1380 1.1 kefren 1381 1.1 kefren /* Send it finally */ 1382 1.1 kefren return send(p->socket, sendspace, 1383 1.1 kefren ntohs(pdu->length) + PDU_VER_LENGTH, 0); 1384 1.1 kefren } 1385 1.1 kefren 1386 1.1 kefren /* 1387 1.1 kefren * Encapsulates TLV into a PDU and sends it to a peer 1388 1.1 kefren */ 1389 1.1 kefren int 1390 1.28 kefren send_tlv(const struct ldp_peer * p, const struct tlv * t) 1391 1.1 kefren { 1392 1.36 riastrad struct in_addr ldp_id; 1393 1.1 kefren struct ldp_pdu pdu; 1394 1.1 kefren 1395 1.36 riastrad inet_aton(LDP_ID, &ldp_id); 1396 1.36 riastrad 1397 1.1 kefren pdu.version = htons(LDP_VERSION); 1398 1.36 riastrad pdu.ldp_id = ldp_id; 1399 1.1 kefren pdu.label_space = 0; 1400 1.1 kefren pdu.length = htons(ntohs(t->length) + TLV_TYPE_LENGTH + 1401 1.1 kefren PDU_PAYLOAD_LENGTH); 1402 1.1 kefren 1403 1.1 kefren return send_message(p, &pdu, t); 1404 1.1 kefren } 1405 1.1 kefren 1406 1.1 kefren 1407 1.1 kefren int 1408 1.28 kefren send_addresses(const struct ldp_peer * p) 1409 1.1 kefren { 1410 1.1 kefren struct address_list_tlv *t; 1411 1.1 kefren int ret; 1412 1.1 kefren 1413 1.1 kefren t = build_address_list_tlv(); 1414 1.1 kefren 1415 1.1 kefren ret = send_tlv(p, (struct tlv *) t); 1416 1.1 kefren free(t); 1417 1.1 kefren return ret; 1418 1.1 kefren 1419 1.1 kefren } 1420