Revision 05476c4d

View differences:

client/birdc.c
19 19
#include "lib/resource.h"
20 20
#include "lib/string.h"
21 21
#include "client/client.h"
22
#include "sysdep/unix/unix.h"
23 22

  
24 23
static int input_hidden_end;
25 24
static int prompt_active;
lib/printf.c
221 221
			continue;
222 222

  
223 223
		case 'm':
224
			if (flags & SPECIAL) {
225
				if (!errno)
226
					continue;
227
				if (size < 2)
228
					return -1;
229
				*str++ = ':';
230
				*str++ = ' ';
231
				start += 2;
232
				size -= 2;
233
			}
224 234
			s = strerror(errno);
225 235
			goto str;
226 236
		case 'M':
lib/socket.h
10 10
#define _BIRD_SOCKET_H_
11 11

  
12 12
#include <errno.h>
13
// #include <sys/socket.h>
13 14

  
14 15
#include "lib/resource.h"
15 16

  
......
43 44
  unsigned lifindex;			/* local interface that received the datagram */
44 45
  /* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
45 46

  
47
  int af;				/* Address family (AF_INET, AF_INET6 or 0 for non-IP) of fd */
46 48
  int fd;				/* System-dependent data */
47 49
  int index;				/* Index in poll buffer */
50
  int rcv_ttl;				/* TTL of last received datagram */
48 51
  node n;
49 52
  void *rbuf_alloc, *tbuf_alloc;
50
  char *password;				/* Password for MD5 authentication */
53
  char *password;			/* Password for MD5 authentication */
54
  char *err;				/* Error message */
51 55
} sock;
52 56

  
53 57
sock *sock_new(pool *);			/* Allocate new socket */
54 58
#define sk_new(X) sock_new(X)		/* Wrapper to avoid name collision with OpenSSL */
55 59

  
56 60
int sk_open(sock *);			/* Open socket */
61
int sk_rx_ready(sock *s);
57 62
int sk_send(sock *, unsigned len);	/* Send data, <0=err, >0=ok, 0=sleep */
58 63
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
59 64
void sk_reallocate(sock *);		/* Free and allocate tbuf & rbuf */
......
61 66
void sk_set_tbsize(sock *s, uint val);	/* Resize TX buffer, keeping content */
62 67
void sk_set_tbuf(sock *s, void *tbuf);	/* Switch TX buffer, NULL-> return to internal */
63 68
void sk_dump_all(void);
64
int sk_set_ttl(sock *s, int ttl);	/* Set transmit TTL for given socket */
65
int sk_set_min_ttl(sock *s, int ttl);	/* Set minimal accepted TTL for given socket */
66 69

  
67
/* Add or remove security associations for given passive socket */
68
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
69
int sk_rx_ready(sock *s);
70
static inline int sk_send_buffer_empty(sock *sk)
71
{ return sk->tbuf == sk->tpos; }
70 72

  
71
/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
72
int sk_setup_multicast(sock *s);	
73
int sk_join_group(sock *s, ip_addr maddr);
74
int sk_leave_group(sock *s, ip_addr maddr);
75 73

  
76 74
#ifdef IPV6
77
int sk_set_ipv6_checksum(sock *s, int offset);
78
int sk_set_icmp_filter(sock *s, int p1, int p2);
75
#define sk_is_ipv4(X) 0
76
#define sk_is_ipv6(X) 1
77
#else
78
#define sk_is_ipv4(X) 1
79
#define sk_is_ipv6(X) 0
79 80
#endif
80 81

  
81
int sk_set_broadcast(sock *s, int enable);
82 82

  
83
static inline int
84
sk_send_buffer_empty(sock *sk)
85
{
86
	return sk->tbuf == sk->tpos;
87
}
83
int sk_setup_multicast(sock *s);	/* Prepare UDP or IP socket for multicasting */
84
int sk_join_group(sock *s, ip_addr maddr);	/* Join multicast group on sk iface */
85
int sk_leave_group(sock *s, ip_addr maddr);	/* Leave multicast group on sk iface */
86
int sk_setup_broadcast(sock *s);
87
int sk_set_ttl(sock *s, int ttl);	/* Set transmit TTL for given socket */
88
int sk_set_min_ttl(sock *s, int ttl);	/* Set minimal accepted TTL for given socket */
89
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
90
int sk_set_ipv6_checksum(sock *s, int offset);
91
int sk_set_icmp6_filter(sock *s, int p1, int p2);
92
void sk_log_error(sock *s, const char *p);
93

  
94
extern int sk_priority_control;		/* Suggested priority for control traffic, should be sysdep define */
88 95

  
89
extern int sk_priority_control;	/* Suggested priority for control traffic, should be sysdep define */
90 96

  
91 97
/* Socket flags */
92 98

  
93
#define SKF_V6ONLY	1	/* Use IPV6_V6ONLY socket option */
94
#define SKF_LADDR_RX	2	/* Report local address for RX packets */
95
#define SKF_TTL_RX	4	/* Report TTL / Hop Limit for RX packets */
96
#define SKF_BIND	8	/* Bind datagram socket to given source address */
99
#define SKF_V4ONLY	0x01	/* Use IPv4 for IP sockets */
100
#define SKF_V6ONLY	0x02	/* Use IPV6_V6ONLY socket option */
101
#define SKF_LADDR_RX	0x04	/* Report local address for RX packets */
102
#define SKF_TTL_RX	0x08	/* Report TTL / Hop Limit for RX packets */
103
#define SKF_BIND	0x10	/* Bind datagram socket to given source address */
97 104

  
98 105
#define SKF_THREAD	0x100	/* Socked used in thread, Do not add to main loop */
99 106
#define SKF_TRUNCATED	0x200	/* Received packet was truncated, set by IO layer */
proto/bfd/packets.c
101 101
  uint err_val = 0;
102 102
  char fb[8];
103 103

  
104
  if ((sk->sport == BFD_CONTROL_PORT) && (sk->ttl < 255))
105
    DROP("wrong TTL", sk->ttl);
104
  if ((sk->sport == BFD_CONTROL_PORT) && (sk->rcv_ttl < 255))
105
    DROP("wrong TTL", sk->rcv_ttl);
106 106

  
107 107
  if (len < BFD_BASE_LEN)
108 108
    DROP("too short", len);
......
209 209
  return sk;
210 210

  
211 211
 err:
212
  sk_log_error(sk, p->p.name);
212 213
  rfree(sk);
213 214
  return NULL;
214 215
}
......
243 244
  return sk;
244 245

  
245 246
 err:
247
  sk_log_error(sk, p->p.name);
246 248
  rfree(sk);
247 249
  return NULL;
248 250
}
proto/bgp/bgp.c
106 106
  struct config *cfg = p->cf->c.global;
107 107
  int errcode;
108 108

  
109
  bgp_counter++;
110

  
111 109
  if (!bgp_listen_sk)
112 110
    bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);
113 111

  
114 112
  if (!bgp_listen_sk)
115 113
    {
116
      bgp_counter--;
117 114
      errcode = BEM_NO_SOCKET;
118 115
      goto err;
119 116
    }
......
121 118
  if (!bgp_linpool)
122 119
    bgp_linpool = lp_new(&root_pool, 4080);
123 120

  
121
  bgp_counter++;
122

  
124 123
  if (p->cf->password)
125
    {
126
      int rv = sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password);
127
      if (rv < 0)
128
	{
129
	  bgp_close(p, 0);
130
	  errcode = BEM_INVALID_MD5;
131
	  goto err;
132
	}
133
    }
124
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
125
      {
126
	sk_log_error(bgp_listen_sk, p->p.name);
127
	bgp_close(p, 0);
128
	errcode = BEM_INVALID_MD5;
129
	goto err;
130
      }
134 131

  
135 132
  return 0;
136 133

  
......
194 191
  bgp_counter--;
195 192

  
196 193
  if (p->cf->password && apply_md5)
197
    sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL);
194
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
195
      sk_log_error(bgp_listen_sk, p->p.name);
198 196

  
199 197
  if (!bgp_counter)
200 198
    {
......
697 695
  bgp_conn_set_state(conn, BS_CONNECT);
698 696

  
699 697
  if (sk_open(s) < 0)
700
    {
701
      bgp_sock_err(s, 0);
702
      return;
703
    }
698
    goto err;
704 699

  
705 700
  /* Set minimal receive TTL if needed */
706 701
  if (p->cf->ttl_security)
707
  {
708
    DBG("Setting minimum received TTL to %d", 256 - hops);
709 702
    if (sk_set_min_ttl(s, 256 - hops) < 0)
710
    {
711
      log(L_ERR "TTL security configuration failed, closing session");
712
      bgp_sock_err(s, 0);
713
      return;
714
    }
715
  }
703
      goto err;
716 704

  
717 705
  DBG("BGP: Waiting for connect success\n");
718 706
  bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
707
  return;
708

  
709
 err:
710
  sk_log_error(s, p->p.name);
711
  bgp_sock_err(s, 0);
712
  return;
719 713
}
720 714

  
721 715
/**
......
760 754
		      sk->dport, acc ? "accepted" : "rejected");
761 755

  
762 756
	    if (!acc)
763
	      goto err;
757
	      goto reject;
764 758

  
765 759
	    int hops = p->cf->multihop ? : 1;
760

  
761
	    if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0)
762
	      goto err;
763

  
766 764
	    if (p->cf->ttl_security)
767
	    {
768
	      /* TTL security support */
769
	      if ((sk_set_ttl(sk, 255) < 0) ||
770
		  (sk_set_min_ttl(sk, 256 - hops) < 0))
771
	      {
772
		log(L_ERR "TTL security configuration failed, closing session");
765
	      if (sk_set_min_ttl(sk, 256 - hops) < 0)
773 766
		goto err;
774
	      }
775
	    }
776
	    else
777
	      sk_set_ttl(sk, hops);
778 767

  
779 768
	    bgp_setup_conn(p, &p->incoming_conn);
780 769
	    bgp_setup_sk(&p->incoming_conn, sk);
781 770
	    bgp_send_open(&p->incoming_conn);
782 771
	    return 0;
772

  
773
	  err:
774
	    sk_log_error(sk, p->p.name);
775
	    log(L_ERR "%s: Incoming connection aborted", p->p.name);
776
	    rfree(sk);
777
	    return 0;
783 778
	  }
784 779
      }
785 780

  
786 781
  log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
787 782
      sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport);
788
 err:
783
 reject:
789 784
  rfree(sk);
790 785
  return 0;
791 786
}
......
816 811
  s->err_hook = bgp_listen_sock_err;
817 812

  
818 813
  if (sk_open(s) < 0)
819
    {
820
      log(L_ERR "BGP: Unable to open listening socket");
821
      rfree(s);
822
      return NULL;
823
    }
814
    goto err;
824 815

  
825 816
  return s;
817

  
818
 err:
819
  sk_log_error(s, "BGP");
820
  log(L_ERR "BGP: Cannot open listening socket");
821
  rfree(s);
822
  return NULL;
826 823
}
827 824

  
828 825
static void
proto/ospf/iface.c
90 90
static int
91 91
ospf_sk_open(struct ospf_iface *ifa)
92 92
{
93
  struct proto_ospf *po = ifa->oa->po;
94

  
93 95
  sock *sk = sk_new(ifa->pool);
94 96
  sk->type = SK_IP;
95 97
  sk->dport = OSPF_PROTO;
......
121 123
    {
122 124
      ifa->all_routers = ifa->addr->brd;
123 125

  
124
      if (sk_set_broadcast(sk, 1) < 0)
126
      if (sk_setup_broadcast(sk) < 0)
125 127
        goto err;
126 128
    }
127 129
    else
......
141 143
  return 1;
142 144

  
143 145
 err:
146
  sk_log_error(sk, po->proto.name);
144 147
  rfree(sk);
145 148
  return 0;
146 149
}
......
151 154
  if (ifa->sk_dr)
152 155
    return;
153 156

  
154
  sk_join_group(ifa->sk, AllDRouters);
157
  if (sk_join_group(ifa->sk, AllDRouters) < 0)
158
    sk_log_error(ifa->sk, ifa->oa->po->proto.name);
159

  
155 160
  ifa->sk_dr = 1;
156 161
}
157 162

  
......
161 166
  if (!ifa->sk_dr)
162 167
    return;
163 168

  
164
  sk_leave_group(ifa->sk, AllDRouters);
169
  if (sk_leave_group(ifa->sk, AllDRouters) < 0)
170
    sk_log_error(ifa->sk, ifa->oa->po->proto.name);
171

  
165 172
  ifa->sk_dr = 0;
166 173
}
167 174

  
168 175
void
169 176
ospf_open_vlink_sk(struct proto_ospf *po)
170 177
{
171
  struct proto *p = &po->proto;
172

  
173 178
  sock *sk = sk_new(po->proto.pool);
174 179
  sk->type = SK_IP;
175 180
  sk->dport = OSPF_PROTO;
......
197 202
  return;
198 203

  
199 204
 err:
205
  sk_log_error(sk, po->proto.name);
206
  log(L_ERR "%s: Cannot open virtual link socket", po->proto.name);
200 207
  rfree(sk);
201
  log(L_ERR "%s: Cannot open virtual link socket", p->name);
202 208
}
203 209

  
204 210
static void
......
463 469
  /* Open socket if interface is not stub */
464 470
  if (! ifa->stub && ! ospf_sk_open(ifa))
465 471
  {
466
    log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->ifname);
472
    log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->name, ifa->ifname);
467 473
    ifa->ioprob = OSPF_I_SK;
468 474
    ifa->stub = 1;
469 475
  }
proto/ospf/packet.c
308 308
    return 1;
309 309
  }
310 310

  
311
  if (ifa->check_ttl && (sk->ttl < 255))
311
  if (ifa->check_ttl && (sk->rcv_ttl < 255))
312 312
  {
313
    log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->ttl);
313
    log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl);
314 314
    return 1;
315 315
  }
316 316

  
proto/radv/packets.c
416 416
  sk->data = ifa;
417 417
  sk->flags = SKF_LADDR_RX;
418 418

  
419
  if (sk_open(sk) != 0)
419
  if (sk_open(sk) < 0)
420 420
    goto err;
421 421

  
422 422
  /* We want listen just to ICMPv6 messages of type RS and RA */
423
  if (sk_set_icmp_filter(sk, ICMPV6_RS, ICMPV6_RA) < 0)
423
  if (sk_set_icmp6_filter(sk, ICMPV6_RS, ICMPV6_RA) < 0)
424 424
    goto err;
425 425

  
426 426
  if (sk_setup_multicast(sk) < 0)
......
433 433
  return 1;
434 434

  
435 435
 err:
436
  sk_log_error(sk, ifa->ra->p.name);
436 437
  rfree(sk);
437 438
  return 0;
438 439
}
proto/rip/rip.c
483 483
  iface = i->iface;
484 484
#endif
485 485

  
486
  if (i->check_ttl && (s->ttl < 255))
486
  if (i->check_ttl && (s->rcv_ttl < 255))
487 487
  {
488 488
    log( L_REMOTE "%s: Discarding packet with TTL %d (< 255) from %I on %s",
489
	 p->name, s->ttl, s->faddr, i->iface->name);
489
	 p->name, s->rcv_ttl, s->faddr, i->iface->name);
490 490
    return 1;
491 491
  }
492 492

  
......
733 733
      log( L_WARN "%s: interface %s is too strange for me", p->name, rif->iface->name );
734 734
  } else {
735 735

  
736
    if (sk_open(rif->sock)<0)
736
    if (sk_open(rif->sock) < 0)
737 737
      goto err;
738 738

  
739 739
    if (rif->multicast)
......
745 745
      }
746 746
    else
747 747
      {
748
	if (sk_set_broadcast(rif->sock, 1) < 0)
748
	if (sk_setup_broadcast(rif->sock) < 0)
749 749
	  goto err;
750 750
      }
751 751
  }
......
755 755
  return rif;
756 756

  
757 757
 err:
758
  log( L_ERR "%s: could not create socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
758
  sk_log_error(rif->sock, p->name);
759
  log(L_ERR "%s: Cannot open socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
759 760
  if (rif->iface) {
760 761
    rfree(rif->sock);
761 762
    mb_free(rif);
sysdep/bsd/krt-sock.c
251 251
    _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
252 252
#endif
253 253

  
254
  fill_in_sockaddr(&dst, net->n.prefix, NULL, 0);
255
  fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
256
  fill_in_sockaddr(&gate, gw, NULL, 0);
254
  sockaddr_fill(&dst,  BIRD_AF, net->n.prefix, NULL, 0);
255
  sockaddr_fill(&mask, BIRD_AF, ipa_mkmask(net->n.pxlen), NULL, 0);
256
  sockaddr_fill(&gate, BIRD_AF, gw, NULL, 0);
257 257

  
258 258
  switch (a->dest)
259 259
  {
......
280 280
          return -1;
281 281
        }
282 282

  
283
        fill_in_sockaddr(&gate, i->addr->ip, NULL, 0);
283
	sockaddr_fill(&dst, BIRD_AF, i->addr->ip, NULL, 0);
284 284
        msg.rtm.rtm_addrs |= RTA_GATEWAY;
285 285
      }
286 286
      break;
......
366 366
  GETADDR(&gate, RTA_GATEWAY);
367 367
  GETADDR(&mask, RTA_NETMASK);
368 368

  
369
  if (sa_family_check(&dst))
370
    get_sockaddr(&dst, &idst, NULL, NULL, 0);
371
  else
369
  if (dst.sa.sa_family != BIRD_AF)
372 370
    SKIP("invalid DST");
373 371

  
374
  /* We will check later whether we have valid gateway addr */
375
  if (sa_family_check(&gate))
376
    get_sockaddr(&gate, &igate, NULL, NULL, 0);
377
  else
378
    igate = IPA_NONE;
372
  idst  = ipa_from_sa(&dst);
373
  imask = ipa_from_sa(&mask);
374
  igate = (gate.sa.sa_family == BIRD_AF) ? ipa_from_sa(&gate) : IPA_NONE;
379 375

  
380 376
  /* We do not test family for RTA_NETMASK, because BSD sends us
381 377
     some strange values, but interpreting them as IPv4/IPv6 works */
382
  get_sockaddr(&mask, &imask, NULL, NULL, 0);
378

  
383 379

  
384 380
  int c = ipa_classify_net(idst);
385 381
  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
......
648 644
  GETADDR (&brd, RTA_BRD);
649 645

  
650 646
  /* Some other family address */
651
  if (!sa_family_check(&addr))
647
  if (addr.sa.sa_family != BIRD_AF)
652 648
    return;
653 649

  
654
  get_sockaddr(&addr, &iaddr, NULL, NULL, 0);
655
  get_sockaddr(&mask, &imask, NULL, NULL, 0);
656
  get_sockaddr(&brd, &ibrd, NULL, NULL, 0);
650
  iaddr = ipa_from_sa(&addr);
651
  imask = ipa_from_sa(&mask);
652
  ibrd  = ipa_from_sa(&brd);
653

  
657 654

  
658 655
  if ((masklen = ipa_mklen(imask)) < 0)
659 656
  {
......
806 803
  mib[0] = CTL_NET;
807 804
  mib[1] = PF_ROUTE;
808 805
  mib[2] = 0;
809
  mib[3] = BIRD_PF;
806
  mib[3] = BIRD_AF;
810 807
  mib[4] = cmd;
811 808
  mib[5] = 0;
812 809
  mcnt = 6;
sysdep/bsd/sysio.h
1 1
/*
2
 *	BIRD Internet Routing Daemon -- NetBSD Multicasting and Network Includes
2
 *	BIRD Internet Routing Daemon -- BSD Multicasting and Network Includes
3 3
 *
4 4
 *	(c) 2004       Ondrej Filip <feela@network.cz>
5 5
 *
6 6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7 7
 */
8 8

  
9
#include <net/if_dl.h>
10
#include <netinet/in_systm.h> // Workaround for some BSDs
11
#include <netinet/ip.h>
12

  
13

  
9 14
#ifdef __NetBSD__
10 15

  
11 16
#ifndef IP_RECVTTL
......
22 27
#define TCP_MD5SIG	TCP_SIGNATURE_ENABLE
23 28
#endif
24 29

  
25
#ifdef IPV6
26 30

  
27
static inline void
28
set_inaddr(struct in6_addr * ia, ip_addr a)
29
{
30
  ipa_hton(a);
31
  memcpy(ia, &a, sizeof(a));
32
}
31
#define SA_LEN(x) (x).sa.sa_len
33 32

  
34
static inline void
35
get_inaddr(ip_addr *a, struct in6_addr *ia)
36
{
37
  memcpy(a, ia, sizeof(*a));
38
  ipa_ntoh(*a);
39
}
40

  
41

  
42
#else
43

  
44
#include <net/if.h>
45
#include <net/if_dl.h>
46
#include <netinet/in_systm.h> // Workaround for some BSDs
47
#include <netinet/ip.h>
48

  
49
static inline void
50
set_inaddr(struct in_addr * ia, ip_addr a)
51
{
52
  ipa_hton(a);
53
  memcpy(&ia->s_addr, &a, sizeof(a));
54
}
55

  
56
static inline void
57
get_inaddr(ip_addr *a, struct in_addr *ia)
58
{
59
  memcpy(a, &ia->s_addr, sizeof(*a));
60
  ipa_ntoh(*a);
61
}
62 33

  
34
/*
35
 *	BSD IPv4 multicast syscalls
36
 */
63 37

  
64
/* BSD Multicast handling for IPv4 */
38
#define INIT_MREQ4(maddr,ifa) \
39
  { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ipa_to_in4(ifa->addr->ip) }
65 40

  
66
static inline char *
67
sysio_setup_multicast(sock *s)
41
static inline int
42
sk_setup_multicast4(sock *s)
68 43
{
69
	struct in_addr m;
70
	u8 zero = 0;
71
	u8 ttl = s->ttl;
44
  struct in_addr ifa = ipa_to_in4(s->iface->addr->ip);
45
  u8 ttl = s->ttl;
46
  u8 n = 0;
72 47

  
73
	if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
74
		return "IP_MULTICAST_LOOP";
48
  /* This defines where should we send _outgoing_ multicasts */
49
  if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &ifa, sizeof(ifa)) < 0)
50
    ERR("IP_MULTICAST_IF");
75 51

  
76
	if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
77
		return "IP_MULTICAST_TTL";
52
  if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
53
    ERR("IP_MULTICAST_TTL");
78 54

  
79
	/* This defines where should we send _outgoing_ multicasts */
80
        set_inaddr(&m, s->iface->addr->ip);
81
	if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
82
		return "IP_MULTICAST_IF";
55
  if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
56
    ERR("IP_MULTICAST_LOOP");
83 57

  
84
	return NULL;
58
  return 0;
85 59
}
86 60

  
87

  
88
static inline char *
89
sysio_join_group(sock *s, ip_addr maddr)
61
static inline int
62
sk_join_group4(sock *s, ip_addr maddr)
90 63
{
91
	struct ip_mreq mreq;
64
  struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
92 65

  
93
	bzero(&mreq, sizeof(mreq));
94
	set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
95
	set_inaddr(&mreq.imr_multiaddr, maddr);
66
  if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
67
    ERR("IP_ADD_MEMBERSHIP");
96 68

  
97
	/* And this one sets interface for _receiving_ multicasts from */
98
	if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
99
		return "IP_ADD_MEMBERSHIP";
100

  
101
	return NULL;
69
  return 0;
102 70
}
103 71

  
104
static inline char *
105
sysio_leave_group(sock *s, ip_addr maddr)
72
static inline int
73
sk_leave_group4(sock *s, ip_addr maddr)
106 74
{
107
	struct ip_mreq mreq;
75
  struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
108 76

  
109
	bzero(&mreq, sizeof(mreq));
110
	set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
111
	set_inaddr(&mreq.imr_multiaddr, maddr);
77
  if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
78
    ERR("IP_ADD_MEMBERSHIP");
112 79

  
113
	/* And this one sets interface for _receiving_ multicasts from */
114
	if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
115
		return "IP_DROP_MEMBERSHIP";
116

  
117
	return NULL;
80
  return 0;
118 81
}
119 82

  
120 83

  
121
/* BSD RX/TX packet info handling for IPv4 */
122
/* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
84
/*
85
 *	BSD IPv4 packet control messages
86
 */
123 87

  
124
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + \
125
		       CMSG_SPACE(sizeof(struct sockaddr_dl)) + \
126
		       CMSG_SPACE(sizeof(char)))
127
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
88
/* It uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
128 89

  
129
static char *
130
sysio_register_cmsgs(sock *s)
131
{
132
  int ok = 1;
133
  if (s->flags & SKF_LADDR_RX)
134
  {
135
    if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
136
      return "IP_RECVDSTADDR";
90
#define CMSG4_SPACE_PKTINFO (CMSG_SPACE(sizeof(struct in_addr)) + \
91
			     CMSG_SPACE(sizeof(struct sockaddr_dl)))
92
#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(char))
137 93

  
138
    if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0)
139
      return "IP_RECVIF";
140
  }
94
static inline int
95
sk_request_cmsg4_pktinfo(sock *s)
96
{
97
  int y = 1;
141 98

  
142
  if ((s->flags & SKF_TTL_RX) &&
143
      (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0))
144
    return "IP_RECVTTL";
99
  if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &y, sizeof(y)) < 0)
100
    ERR("IP_RECVDSTADDR");
145 101

  
102
  if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &y, sizeof(y)) < 0)
103
    ERR("IP_RECVIF");
146 104

  
147
  return NULL;
105
  return 0;
148 106
}
149 107

  
150
static inline void
151
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
108
static inline int
109
sk_request_cmsg4_ttl(sock *s)
152 110
{
153
  struct cmsghdr *cm;
154
  struct in_addr *ra = NULL;
155
  struct sockaddr_dl *ri = NULL;
156
  unsigned char *ttl = NULL;
157

  
158
  for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
159
  {
160
    if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
161
      ra = (struct in_addr *) CMSG_DATA(cm);
162

  
163
    if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
164
      ri = (struct sockaddr_dl *) CMSG_DATA(cm);
165

  
166
    if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVTTL)
167
      ttl = (unsigned char *) CMSG_DATA(cm);
168
  }
111
  int y = 1;
169 112

  
170
  if (s->flags & SKF_LADDR_RX)
171
  {
172
    s->laddr = IPA_NONE;
173
    s->lifindex = 0;
113
  if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
114
    ERR("IP_RECVTTL");
174 115

  
175
    if (ra)
176
      get_inaddr(&s->laddr, ra);
177
    if (ri)
178
      s->lifindex = ri->sdl_index;
179
  }
116
  return 0;
117
}
180 118

  
181
  if (s->flags & SKF_TTL_RX)
182
    s->ttl = ttl ? *ttl : -1;
119
static inline void
120
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
121
{
122
  if (cm->cmsg_type == IP_RECVDSTADDR)
123
    s->laddr = ipa_from_in4(* (struct in_addr *) CMSG_DATA(cm));
183 124

  
184
  // log(L_WARN "RX %I %d", s->laddr, s->lifindex);
125
  if (cm->cmsg_type == IP_RECVIF)
126
    s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
185 127
}
186 128

  
187
/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
129
static inline void
130
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
131
{
132
  if (cm->cmsg_type == IP_RECVTTL)
133
    s->rcv_ttl = * (unsigned char *) CMSG_DATA(cm);
134
}
188 135

  
189 136
static inline void
190
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
137
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
191 138
{
139
  /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
140

  
192 141
#ifdef IP_SENDSRCADDR
193 142
  struct cmsghdr *cm;
194 143
  struct in_addr *sa;
......
202 151
  cm->cmsg_len = CMSG_LEN(sizeof(*sa));
203 152

  
204 153
  sa = (struct in_addr *) CMSG_DATA(cm);
205
  set_inaddr(sa, s->saddr);
154
  *sa = ipa_to_in4(s->saddr);
206 155

  
207 156
  msg->msg_controllen = cm->cmsg_len;
208 157
#endif
209 158
}
210 159

  
211

  
212 160
static void
213
fill_ip_header(sock *s, void *hdr, int dlen)
161
sk_prepare_ip_header(sock *s, void *hdr, int dlen)
214 162
{
215 163
  struct ip *ip = hdr;
216 164

  
......
222 170
  ip->ip_len = 20 + dlen;
223 171
  ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
224 172
  ip->ip_p = s->dport;
225
  set_inaddr(&ip->ip_src, s->saddr);
226
  set_inaddr(&ip->ip_dst, s->daddr);
173
  ip->ip_src = ipa_to_in4(s->saddr);
174
  ip->ip_dst = ipa_to_in4(s->daddr);
227 175

  
228 176
#ifdef __OpenBSD__
229 177
  /* OpenBSD expects ip_len in network order, other BSDs expect host order */
......
231 179
#endif
232 180
}
233 181

  
234
#endif
235 182

  
183
/*
184
 *	Miscellaneous BSD socket syscalls
185
 */
236 186

  
237
#include <netinet/tcp.h>
238 187
#ifndef TCP_KEYLEN_MAX
239 188
#define TCP_KEYLEN_MAX 80
240 189
#endif
......
248 197
 * management.
249 198
 */
250 199

  
251
static int
252
sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
200
int
201
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
253 202
{
254 203
  int enable = 0;
255
  if (passwd)
256
    {
257
      int len = strlen(passwd);
258

  
259
      enable = len ? TCP_SIG_SPI : 0;
260

  
261
      if (len > TCP_KEYLEN_MAX)
262
	{
263
	  log(L_ERR "MD5 password too long");
264
	  return -1;
265
	}
266
    }
267

  
268
  int rv = setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable));
269

  
270
  if (rv < 0) 
271
    {
272
      if (errno == ENOPROTOOPT)
273
	log(L_ERR "Kernel does not support TCP MD5 signatures");
274
      else
275
	log(L_ERR "sk_set_md5_auth_int: setsockopt: %m");
276
    }
277

  
278
  return rv;
279
}
280 204

  
205
  if (passwd && *passwd)
206
  {
207
    int len = strlen(passwd);
208
    enable = TCP_SIG_SPI;
209

  
210
    if (len > TCP_KEYLEN_MAX)
211
      ERR_MSG("MD5 password too long");
212
  }
213

  
214
  if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
215
  {
216
    if (errno == ENOPROTOOPT)
217
      ERR_MSG("Kernel does not support TCP MD5 signatures");
218
    else
219
      ERR("TCP_MD5SIG");
220
  }
281 221

  
282
#ifndef IPV6
222
  return 0;
223
}
283 224

  
284
static int
225
static inline int
285 226
sk_set_min_ttl4(sock *s, int ttl)
286 227
{
287 228
  if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
288 229
  {
289 230
    if (errno == ENOPROTOOPT)
290
      log(L_ERR "Kernel does not support IPv4 TTL security");
231
      ERR_MSG("Kernel does not support IPv4 TTL security");
291 232
    else
292
      log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
293

  
294
    return -1;
233
      ERR("IP_MINTTL");
295 234
  }
296 235

  
297 236
  return 0;
298 237
}
299 238

  
300
#else /* IPv6 */
301

  
302
static int
239
static inline int
303 240
sk_set_min_ttl6(sock *s, int ttl)
304 241
{
305
  log(L_ERR "IPv6 TTL security not supported");
306
  return -1;
242
  ERR_MSG("Kernel does not support IPv6 TTL security");
307 243
}
308 244

  
309
#endif
245
static inline int
246
sk_disable_mtu_disc4(sock *s)
247
{
248
  /* TODO: Set IP_DONTFRAG to 0 ? */
249
  return 0;
250
}
310 251

  
252
static inline int
253
sk_disable_mtu_disc6(sock *s)
254
{
255
  /* TODO: Set IPV6_DONTFRAG to 0 ? */
256
  return 0;
257
}
311 258

  
312 259
int sk_priority_control = -1;
313 260

  
314
static int
261
static inline int
315 262
sk_set_priority(sock *s, int prio UNUSED)
316 263
{
317
  log(L_WARN "Socket priority not supported");
318
  return -1;
264
  ERR_MSG("Socket priority not supported");
319 265
}
sysdep/linux/netlink.c
104 104
  req.nh.nlmsg_type = cmd;
105 105
  req.nh.nlmsg_len = sizeof(req);
106 106
  req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
107
  /* Is it important which PF_* is used for link-level interface scan?
108
     It seems that some information is available only when PF_INET is used. */
109
  req.g.rtgen_family = (cmd == RTM_GETLINK) ? PF_INET : BIRD_PF;
107
  /* Is it important which AF_* is used for link-level interface scan?
108
     It seems that some information is available only when AF_INET is used. */
109
  req.g.rtgen_family = (cmd == RTM_GETLINK) ? AF_INET : BIRD_AF;
110 110
  nl_send(&nl_scan, &req.nh);
111 111
}
112 112

  
......
1069 1069
  sk->type = SK_MAGIC;
1070 1070
  sk->rx_hook = nl_async_hook;
1071 1071
  sk->fd = fd;
1072
  if (sk_open(sk))
1072
  if (sk_open(sk) < 0)
1073 1073
    bug("Netlink: sk_open failed");
1074 1074
}
1075 1075

  
sysdep/linux/sysio.h
6 6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7 7
 */
8 8

  
9
#include <net/if.h>
10

  
11
#ifdef IPV6
12

  
13
#ifndef IPV6_UNICAST_HOPS
14
/* Needed on glibc 2.0 systems */
15
#include <linux/in6.h>
16
#define CONFIG_IPV6_GLIBC_20
17
#endif
18

  
19
static inline void
20
set_inaddr(struct in6_addr *ia, ip_addr a)
21
{
22
  ipa_hton(a);
23
  memcpy(ia, &a, sizeof(a));
24
}
25

  
26
static inline void
27
get_inaddr(ip_addr *a, struct in6_addr *ia)
28
{
29
  memcpy(a, ia, sizeof(*a));
30
  ipa_ntoh(*a);
31
}
32

  
33
#else
34

  
35
static inline void
36
set_inaddr(struct in_addr *ia, ip_addr a)
37
{
38
  ipa_hton(a);
39
  memcpy(&ia->s_addr, &a, sizeof(a));
40
}
41

  
42
static inline void
43
get_inaddr(ip_addr *a, struct in_addr *ia)
44
{
45
  memcpy(a, &ia->s_addr, sizeof(*a));
46
  ipa_ntoh(*a);
47
}
48

  
49 9

  
50 10
#ifndef HAVE_STRUCT_IP_MREQN
51 11
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
52 12
struct ip_mreqn
53 13
{
54
	struct in_addr	imr_multiaddr;		/* IP multicast address of group */
55
	struct in_addr	imr_address;		/* local IP address of interface */
56
	int		imr_ifindex;		/* Interface index */
14
  struct in_addr imr_multiaddr;			/* IP multicast address of group */
15
  struct in_addr imr_address;			/* local IP address of interface */
16
  int		 imr_ifindex;			/* Interface index */
57 17
};
58 18
#endif
59 19

  
20
#ifndef IP_MINTTL
21
#define IP_MINTTL 21
22
#endif
60 23

  
61
static inline void fill_mreqn(struct ip_mreqn *m, ip_addr maddr, struct iface *ifa)
62
{
63
  bzero(m, sizeof(*m));
64
  m->imr_ifindex = ifa->index;
65
  set_inaddr(&m->imr_multiaddr, maddr);
66
}
24
#ifndef IPV6_TCLASS
25
#define IPV6_TCLASS 67
26
#endif
67 27

  
68
static inline char *
69
sysio_setup_multicast(sock *s)
70
{
71
  struct ip_mreqn m;
72
  int zero = 0;
28
#ifndef IPV6_MINHOPCOUNT
29
#define IPV6_MINHOPCOUNT 73
30
#endif
73 31

  
74
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
75
    return "IP_MULTICAST_LOOP";
76 32

  
77
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
78
    return "IP_MULTICAST_TTL";
33
#ifndef TCP_MD5SIG
79 34

  
80
  /* This defines where should we send _outgoing_ multicasts */
81
  fill_mreqn(&m, IPA_NONE, s->iface);
82
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
83
    return "IP_MULTICAST_IF";
35
#define TCP_MD5SIG  14
36
#define TCP_MD5SIG_MAXKEYLEN 80
84 37

  
85
  return NULL;
86
}
38
struct tcp_md5sig {
39
  struct  sockaddr_storage tcpm_addr;             /* address associated */
40
  u16   __tcpm_pad1;                              /* zero */
41
  u16   tcpm_keylen;                              /* key length */
42
  u32   __tcpm_pad2;                              /* zero */
43
  u8    tcpm_key[TCP_MD5SIG_MAXKEYLEN];           /* key (binary) */
44
};
87 45

  
88
static inline char *
89
sysio_join_group(sock *s, ip_addr maddr)
90
{
91
  struct ip_mreqn m;
46
#endif
92 47

  
93
  /* And this one sets interface for _receiving_ multicasts from */
94
  fill_mreqn(&m, maddr, s->iface);
95
  if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
96
    return "IP_ADD_MEMBERSHIP";
97 48

  
98
  return NULL;
99
}
49
/* Linux does not care if sa_len is larger than needed */
50
#define SA_LEN(x) sizeof(sockaddr)
100 51

  
101
static inline char *
102
sysio_leave_group(sock *s, ip_addr maddr)
103
{
104
  struct ip_mreqn m;
105 52

  
106
  /* And this one sets interface for _receiving_ multicasts from */
107
  fill_mreqn(&m, maddr, s->iface);
108
  if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
109
    return "IP_DROP_MEMBERSHIP";
53
/*
54
 *	Linux IPv4 multicast syscalls
55
 */
110 56

  
111
  return NULL;
112
}
57
#define INIT_MREQ4(maddr,ifa) \
58
  { .imr_multiaddr = ipa_to_in4(maddr), .imr_ifindex = ifa->index }
113 59

  
114
#endif
60
static inline int
61
sk_setup_multicast4(sock *s)
62
{
63
  struct ip_mreqn mr = { .imr_ifindex = s->iface->index };
64
  int ttl = s->ttl;
65
  int n = 0;
115 66

  
67
  /* This defines where should we send _outgoing_ multicasts */
68
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) < 0)
69
    ERR("IP_MULTICAST_IF");
116 70

  
117
/* For the case that we have older libc headers */
118
/* Copied from Linux kernel file include/linux/tcp.h */
71
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
72
    ERR("IP_MULTICAST_TTL");
119 73

  
120
#ifndef TCP_MD5SIG
74
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
75
    ERR("IP_MULTICAST_LOOP");
121 76

  
122
#define TCP_MD5SIG  14
123
#define TCP_MD5SIG_MAXKEYLEN 80
77
  return 0;
78
}
124 79

  
125
#include <linux/types.h>
80
static inline int
81
sk_join_group4(sock *s, ip_addr maddr)
82
{
83
  struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
126 84

  
127
struct tcp_md5sig {
128
  struct  sockaddr_storage tcpm_addr;             /* address associated */
129
  __u16   __tcpm_pad1;                            /* zero */
130
  __u16   tcpm_keylen;                            /* key length */
131
  __u32   __tcpm_pad2;                            /* zero */
132
  __u8    tcpm_key[TCP_MD5SIG_MAXKEYLEN];         /* key (binary) */
133
};
85
  if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
86
    ERR("IP_ADD_MEMBERSHIP");
134 87

  
135
#endif
88
  return 0;
89
}
136 90

  
137
static int
138
sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
91
static inline int
92
sk_leave_group4(sock *s, ip_addr maddr)
139 93
{
140
  struct tcp_md5sig md5;
94
  struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
141 95

  
142
  memset(&md5, 0, sizeof(md5));
143
  memcpy(&md5.tcpm_addr, (struct sockaddr *) sa, sizeof(*sa));
96
  if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
97
    ERR("IP_DROP_MEMBERSHIP");
144 98

  
145
  if (passwd)
146
    {
147
      int len = strlen(passwd);
148

  
149
      if (len > TCP_MD5SIG_MAXKEYLEN)
150
	{
151
	  log(L_ERR "MD5 password too long");
152
	  return -1;
153
	}
154

  
155
      md5.tcpm_keylen = len;
156
      memcpy(&md5.tcpm_key, passwd, len);
157
    }
158

  
159
  int rv = setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5));
160

  
161
  if (rv < 0) 
162
    {
163
      if (errno == ENOPROTOOPT)
164
	log(L_ERR "Kernel does not support TCP MD5 signatures");
165
      else
166
	log(L_ERR "sk_set_md5_auth_int: setsockopt: %m");
167
    }
168

  
169
  return rv;
99
  return 0;
170 100
}
171 101

  
172 102

  
173
#ifndef IPV6
103
/*
104
 *	Linux IPv4 packet control messages
105
 */
174 106

  
175
/* RX/TX packet info handling for IPv4 */
176 107
/* Mostly similar to standardized IPv6 code */
177 108

  
178
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(int)))
179
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo))
109
#define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
110
#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int))
180 111

  
181
static char *
182
sysio_register_cmsgs(sock *s)
112
static inline int
113
sk_request_cmsg4_pktinfo(sock *s)
183 114
{
184
  int ok = 1;
115
  int y = 1;
185 116

  
186
  if ((s->flags & SKF_LADDR_RX) &&
187
      (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0))
188
    return "IP_PKTINFO";
117
  if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &y, sizeof(y)) < 0)
118
    ERR("IP_PKTINFO");
189 119

  
190
  if ((s->flags & SKF_TTL_RX) &&
191
      (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0))
192
    return "IP_RECVTTL";
193

  
194
  return NULL;
120
  return 0;
195 121
}
196 122

  
197
static void
198
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
123
static inline int
124
sk_request_cmsg4_ttl(sock *s)
199 125
{
200
  struct cmsghdr *cm;
201
  struct in_pktinfo *pi = NULL;
202
  int *ttl = NULL;
126
  int y = 1;
203 127

  
204
  for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
205
  {
206
    if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_PKTINFO)
207
      pi = (struct in_pktinfo *) CMSG_DATA(cm);
128
  if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
129
    ERR("IP_RECVTTL");
208 130

  
209
    if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_TTL)
210
      ttl = (int *) CMSG_DATA(cm);
211
  }
131
  return 0;
132
}
212 133

  
213
  if (s->flags & SKF_LADDR_RX)
134
static inline void
135
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
136
{
137
  if (cm->cmsg_type == IP_PKTINFO)
214 138
  {
215
    if (pi)
216
    {
217
      get_inaddr(&s->laddr, &pi->ipi_addr);
218
      s->lifindex = pi->ipi_ifindex;
219
    }
220
    else
221
    {
222
      s->laddr = IPA_NONE;
223
      s->lifindex = 0;
224
    }
139
    struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
140
    s->laddr = ipa_from_in4(pi->ipi_addr);
141
    s->lifindex = pi->ipi_ifindex;
225 142
  }
143
}
226 144

  
227
  if (s->flags & SKF_TTL_RX)
228
    s->ttl = ttl ? *ttl : -1;
229

  
230
  return;
145
static inline void
146
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
147
{
148
  if (cm->cmsg_type == IP_TTL)
149
    s->rcv_ttl = * (int *) CMSG_DATA(cm);
231 150
}
232 151

  
233
static void
234
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
152
static inline void
153
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
235 154
{
236 155
  struct cmsghdr *cm;
237 156
  struct in_pktinfo *pi;
......
246 165

  
247 166
  pi = (struct in_pktinfo *) CMSG_DATA(cm);
248 167
  pi->ipi_ifindex = s->iface ? s->iface->index : 0;
249
  set_inaddr(&pi->ipi_spec_dst, s->saddr);
250
  set_inaddr(&pi->ipi_addr, IPA_NONE);
168
  pi->ipi_spec_dst = ipa_to_in4(s->saddr);
169
  pi->ipi_addr = ipa_to_in4(IPA_NONE);
251 170

  
252 171
  msg->msg_controllen = cm->cmsg_len;
253 172
}
254 173

  
255 174

  
256
#endif
175
/*
176
 *	Miscellaneous Linux socket syscalls
177
 */
257 178

  
179
int
180
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
181
{
182
  struct tcp_md5sig md5;
258 183

  
259
#ifndef IP_MINTTL
260
#define IP_MINTTL 21
261
#endif
184
  memset(&md5, 0, sizeof(md5));
185
  sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, a, ifa, 0);
262 186

  
263
#ifndef IPV6_MINHOPCOUNT
264
#define IPV6_MINHOPCOUNT 73
265
#endif
187
  if (passwd)
188
  {
189
    int len = strlen(passwd);
190

  
191
    if (len > TCP_MD5SIG_MAXKEYLEN)
192
      ERR_MSG("MD5 password too long");
266 193

  
194
    md5.tcpm_keylen = len;
195
    memcpy(&md5.tcpm_key, passwd, len);
196
  }
197

  
198
  if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
199
  {
200
    if (errno == ENOPROTOOPT)
201
      ERR_MSG("Kernel does not support TCP MD5 signatures");
202
    else
203
      ERR("TCP_MD5SIG");
204
  }
267 205

  
268
#ifndef IPV6
206
  return 0;
207
}
269 208

  
270
static int
209
static inline int
271 210
sk_set_min_ttl4(sock *s, int ttl)
272 211
{
273 212
  if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
274 213
  {
275 214
    if (errno == ENOPROTOOPT)
276
      log(L_ERR "Kernel does not support IPv4 TTL security");
215
      ERR_MSG("Kernel does not support IPv4 TTL security");
277 216
    else
278
      log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
279

  
280
    return -1;
217
      ERR("IP_MINTTL");
281 218
  }
282 219

  
283 220
  return 0;
284 221
}
285 222

  
286
#else
287

  
288
static int
223
static inline int
289 224
sk_set_min_ttl6(sock *s, int ttl)
290 225
{
291 226
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
292 227
  {
293 228
    if (errno == ENOPROTOOPT)
294
      log(L_ERR "Kernel does not support IPv6 TTL security");
229
      ERR_MSG("Kernel does not support IPv6 TTL security");
295 230
    else
296
      log(L_ERR "sk_set_min_ttl6: setsockopt: %m");
297

  
298
    return -1;
231
      ERR("IPV6_MINHOPCOUNT");
299 232
  }
300 233

  
301 234
  return 0;
302 235
}
303 236

  
304
#endif
237
static inline int
238
sk_disable_mtu_disc4(sock *s)
239
{
240
  int dont = IP_PMTUDISC_DONT;
305 241

  
242
  if (setsockopt(s->fd, SOL_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
243
    ERR("IP_MTU_DISCOVER");
306 244

  
307
#ifndef IPV6_TCLASS
308
#define IPV6_TCLASS 67
309
#endif
245
  return 0;
246
}
247

  
248
static inline int
249
sk_disable_mtu_disc6(sock *s)
250
{
251
  int dont = IPV6_PMTUDISC_DONT;
252

  
253
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
254
    ERR("IPV6_MTU_DISCOVER");
255

  
256
  return 0;
257
}
310 258

  
311 259
int sk_priority_control = 7;
312 260

  
313
static int
261
static inline int
314 262
sk_set_priority(sock *s, int prio)
315 263
{
316 264
  if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
317
  {
318
    log(L_WARN "sk_set_priority: setsockopt: %m");
319
    return -1;
320
  }
265
    ERR("SO_PRIORITY");
321 266

  
322 267
  return 0;
323 268
}
269

  
sysdep/unix/io.c
22 22
#include <unistd.h>
23 23
#include <fcntl.h>
24 24
#include <errno.h>
25
#include <net/if.h>
25 26
#include <netinet/in.h>
26 27
#include <netinet/tcp.h>
27 28
#include <netinet/udp.h>
......
470 471
    strcpy(x, "<too-long>");
471 472
}
472 473

  
474

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff