]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * OSPF network related functions | |
3 | * Copyright (C) 1999 Toshiaki Takada | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
896014f4 DL |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; see the file COPYING; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 20 | */ |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "thread.h" | |
25 | #include "linklist.h" | |
26 | #include "prefix.h" | |
27 | #include "if.h" | |
28 | #include "sockunion.h" | |
29 | #include "log.h" | |
30 | #include "sockopt.h" | |
edd7c245 | 31 | #include "privs.h" |
32 | ||
33 | extern struct zebra_privs_t ospfd_privs; | |
718e3744 | 34 | |
35 | #include "ospfd/ospfd.h" | |
36 | #include "ospfd/ospf_network.h" | |
37 | #include "ospfd/ospf_interface.h" | |
38 | #include "ospfd/ospf_asbr.h" | |
39 | #include "ospfd/ospf_lsa.h" | |
40 | #include "ospfd/ospf_lsdb.h" | |
41 | #include "ospfd/ospf_neighbor.h" | |
42 | #include "ospfd/ospf_packet.h" | |
43 | ||
edd7c245 | 44 | |
45 | ||
718e3744 | 46 | /* Join to the OSPF ALL SPF ROUTERS multicast group. */ |
47 | int | |
48 | ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, | |
b892f1dd | 49 | ifindex_t ifindex) |
718e3744 | 50 | { |
51 | int ret; | |
52 | ||
69bf3a39 | 53 | ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, |
4a3867d0 | 54 | p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), |
718e3744 | 55 | ifindex); |
56 | if (ret < 0) | |
3dc56b5b | 57 | zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " |
58 | "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " | |
59 | "on # of multicast group memberships has been exceeded?", | |
60 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 61 | else |
ec70497b | 62 | zlog_debug ("interface %s [%u] join AllSPFRouters Multicast group.", |
42c98199 | 63 | inet_ntoa (p->u.prefix4), ifindex); |
718e3744 | 64 | |
65 | return ret; | |
66 | } | |
67 | ||
68 | int | |
69 | ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, | |
b892f1dd | 70 | ifindex_t ifindex) |
718e3744 | 71 | { |
72 | int ret; | |
73 | ||
69bf3a39 | 74 | ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, |
4a3867d0 | 75 | p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), |
718e3744 | 76 | ifindex); |
77 | if (ret < 0) | |
3dc56b5b | 78 | zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " |
79 | "ifindex %u, AllSPFRouters): %s", | |
80 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 81 | else |
ec70497b PJ |
82 | zlog_debug ("interface %s [%u] leave AllSPFRouters Multicast group.", |
83 | inet_ntoa (p->u.prefix4), ifindex); | |
718e3744 | 84 | |
85 | return ret; | |
86 | } | |
87 | ||
88 | /* Join to the OSPF ALL Designated ROUTERS multicast group. */ | |
89 | int | |
b892f1dd | 90 | ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) |
718e3744 | 91 | { |
92 | int ret; | |
93 | ||
69bf3a39 | 94 | ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, |
4a3867d0 | 95 | p->u.prefix4, htonl (OSPF_ALLDROUTERS), |
718e3744 | 96 | ifindex); |
97 | if (ret < 0) | |
3dc56b5b | 98 | zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " |
99 | "ifindex %u, AllDRouters): %s; perhaps a kernel limit " | |
100 | "on # of multicast group memberships has been exceeded?", | |
101 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 102 | else |
ec70497b PJ |
103 | zlog_debug ("interface %s [%u] join AllDRouters Multicast group.", |
104 | inet_ntoa (p->u.prefix4), ifindex); | |
718e3744 | 105 | |
106 | return ret; | |
107 | } | |
108 | ||
109 | int | |
b892f1dd | 110 | ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) |
718e3744 | 111 | { |
112 | int ret; | |
113 | ||
69bf3a39 | 114 | ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, |
4a3867d0 | 115 | p->u.prefix4, htonl (OSPF_ALLDROUTERS), |
718e3744 | 116 | ifindex); |
117 | if (ret < 0) | |
3dc56b5b | 118 | zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " |
119 | "ifindex %u, AllDRouters): %s", | |
120 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 121 | else |
ec70497b PJ |
122 | zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.", |
123 | inet_ntoa (p->u.prefix4), ifindex); | |
718e3744 | 124 | |
125 | return ret; | |
126 | } | |
127 | ||
128 | int | |
b892f1dd | 129 | ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex) |
718e3744 | 130 | { |
131 | u_char val; | |
132 | int ret, len; | |
c5bdb09f | 133 | |
718e3744 | 134 | /* Prevent receiving self-origined multicast packets. */ |
c5bdb09f | 135 | ret = setsockopt_ipv4_multicast_loop (top->fd, 0); |
718e3744 | 136 | if (ret < 0) |
3dc56b5b | 137 | zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", |
138 | top->fd, safe_strerror(errno)); | |
718e3744 | 139 | |
140 | /* Explicitly set multicast ttl to 1 -- endo. */ | |
141 | val = 1; | |
c5bdb09f | 142 | len = sizeof (val); |
718e3744 | 143 | ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len); |
144 | if (ret < 0) | |
3dc56b5b | 145 | zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", |
146 | top->fd, safe_strerror (errno)); | |
718e3744 | 147 | |
4a3867d0 | 148 | ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, ifindex); |
718e3744 | 149 | if (ret < 0) |
3dc56b5b | 150 | zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " |
151 | "ifindex %u): %s", | |
152 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 153 | |
154 | return ret; | |
155 | } | |
156 | ||
157 | int | |
158 | ospf_sock_init (void) | |
159 | { | |
160 | int ospf_sock; | |
1423c809 | 161 | int ret, hincl = 1; |
a78d75b0 | 162 | int bufsize = (8 * 1024 * 1024); |
718e3744 | 163 | |
edd7c245 | 164 | if ( ospfd_privs.change (ZPRIVS_RAISE) ) |
165 | zlog_err ("ospf_sock_init: could not raise privs, %s", | |
6099b3b5 | 166 | safe_strerror (errno) ); |
edd7c245 | 167 | |
718e3744 | 168 | ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP); |
169 | if (ospf_sock < 0) | |
170 | { | |
0b7d97d2 | 171 | int save_errno = errno; |
edd7c245 | 172 | if ( ospfd_privs.change (ZPRIVS_LOWER) ) |
173 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 174 | safe_strerror (errno) ); |
0b7d97d2 | 175 | zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno)); |
176 | exit(1); | |
718e3744 | 177 | } |
edd7c245 | 178 | |
5bd4189c | 179 | #ifdef IP_HDRINCL |
180 | /* we will include IP header with packet */ | |
181 | ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl)); | |
182 | if (ret < 0) | |
183 | { | |
0b7d97d2 | 184 | int save_errno = errno; |
5bd4189c | 185 | if ( ospfd_privs.change (ZPRIVS_LOWER) ) |
186 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 187 | safe_strerror (errno) ); |
0b7d97d2 | 188 | zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s", |
189 | ospf_sock, safe_strerror(save_errno)); | |
5bd4189c | 190 | } |
191 | #elif defined (IPTOS_PREC_INTERNETCONTROL) | |
192 | #warning "IP_HDRINCL not available on this system" | |
193 | #warning "using IPTOS_PREC_INTERNETCONTROL" | |
1423c809 | 194 | ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL); |
718e3744 | 195 | if (ret < 0) |
196 | { | |
0b7d97d2 | 197 | int save_errno = errno; |
edd7c245 | 198 | if ( ospfd_privs.change (ZPRIVS_LOWER) ) |
199 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 200 | safe_strerror (errno) ); |
0b7d97d2 | 201 | zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s", |
202 | tos, ospf_sock, safe_strerror(save_errno)); | |
718e3744 | 203 | close (ospf_sock); /* Prevent sd leak. */ |
204 | return ret; | |
205 | } | |
5bd4189c | 206 | #else /* !IPTOS_PREC_INTERNETCONTROL */ |
207 | #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL" | |
208 | zlog_warn ("IP_HDRINCL option not available"); | |
209 | #endif /* IP_HDRINCL */ | |
718e3744 | 210 | |
ac191232 | 211 | ret = setsockopt_ifindex (AF_INET, ospf_sock, 1); |
212 | ||
2dd8bb4e | 213 | if (ret < 0) |
3dc56b5b | 214 | zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock); |
edd7c245 | 215 | |
216 | if (ospfd_privs.change (ZPRIVS_LOWER)) | |
217 | { | |
218 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 219 | safe_strerror (errno) ); |
edd7c245 | 220 | } |
a78d75b0 | 221 | |
6228a3b8 RW |
222 | setsockopt_so_sendbuf (ospf_sock, bufsize); |
223 | setsockopt_so_recvbuf (ospf_sock, bufsize); | |
a78d75b0 | 224 | |
718e3744 | 225 | return ospf_sock; |
226 | } |