Revision 48e5f32d sysdep/unix/io.c

View differences:

sysdep/unix/io.c
23 23
#include <fcntl.h>
24 24
#include <errno.h>
25 25
#include <netinet/in.h>
26
#include <netinet/tcp.h>
27
#include <netinet/udp.h>
26 28
#include <netinet/icmp6.h>
27 29

  
28 30
#include "nest/bird.h"
......
489 491
#define SOL_IPV6 IPPROTO_IPV6
490 492
#endif
491 493

  
494
#ifndef SOL_ICMPV6
495
#define SOL_ICMPV6 IPPROTO_ICMPV6
496
#endif
497

  
498

  
492 499
static list sock_list;
493 500
static struct birdsock *current_sock;
494 501
static struct birdsock *stored_sock;
......
553 560
}
554 561

  
555 562
void
563
sk_set_rbsize(sock *s, uint val)
564
{
565
  ASSERT(s->rbuf_alloc == s->rbuf);
566

  
567
  if (s->rbsize == val)
568
    return;
569

  
570
  s->rbsize = val;
571
  xfree(s->rbuf_alloc);
572
  s->rbuf_alloc = xmalloc(val);
573
  s->rpos = s->rbuf = s->rbuf_alloc;
574
}
575

  
576
void
577
sk_set_tbsize(sock *s, uint val)
578
{
579
  ASSERT(s->tbuf_alloc == s->tbuf);
580

  
581
  if (s->tbsize == val)
582
    return;
583

  
584
  byte *old_tbuf = s->tbuf;
585

  
586
  s->tbsize = val;
587
  s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
588
  s->tpos = s->tbuf + (s->tpos - old_tbuf);
589
  s->ttx  = s->tbuf + (s->ttx  - old_tbuf);
590
}
591

  
592
void
593
sk_set_tbuf(sock *s, void *tbuf)
594
{
595
  s->tbuf = tbuf ?: s->tbuf_alloc;
596
  s->ttx = s->tpos = s->tbuf;
597
}
598

  
599
void
556 600
sk_reallocate(sock *s)
557 601
{
558 602
  sk_free_bufs(s);
......
703 747
  int ok = 1;
704 748

  
705 749
  if ((s->flags & SKF_LADDR_RX) &&
706
      (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0))
750
      (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0))
707 751
    return "IPV6_RECVPKTINFO";
708 752

  
709 753
  if ((s->flags & SKF_TTL_RX) &&
710
      (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0))
754
      (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0))
711 755
    return "IPV6_RECVHOPLIMIT";
712 756

  
713 757
  return NULL;
......
722 766

  
723 767
  for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
724 768
  {
725
    if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
769
    if (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
726 770
      pi = (struct in6_pktinfo *) CMSG_DATA(cm);
727 771

  
728
    if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT)
772
    if (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT)
729 773
      hlim = (int *) CMSG_DATA(cm);
730 774
  }
731 775

  
......
749 793
  return;
750 794
}
751 795

  
752
/*
753 796
static void
754 797
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
755 798
{
756 799
  struct cmsghdr *cm;
757 800
  struct in6_pktinfo *pi;
758 801

  
759
  if (!(s->flags & SKF_LADDR_TX))
760
    return;
761

  
762 802
  msg->msg_control = cbuf;
763 803
  msg->msg_controllen = cbuflen;
764 804

  
765 805
  cm = CMSG_FIRSTHDR(msg);
766
  cm->cmsg_level = IPPROTO_IPV6;
806
  cm->cmsg_level = SOL_IPV6;
767 807
  cm->cmsg_type = IPV6_PKTINFO;
768 808
  cm->cmsg_len = CMSG_LEN(sizeof(*pi));
769 809

  
770 810
  pi = (struct in6_pktinfo *) CMSG_DATA(cm);
771
  set_inaddr(&pi->ipi6_addr, s->saddr);
772 811
  pi->ipi6_ifindex = s->iface ? s->iface->index : 0;
812
  set_inaddr(&pi->ipi6_addr, s->saddr);
773 813

  
774 814
  msg->msg_controllen = cm->cmsg_len;
775
  return;
776 815
}
777
*/
816

  
778 817
#endif
779 818

  
780 819
static char *
......
786 825
#else
787 826
  if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
788 827
    return "IP_TTL";
789
#ifdef CONFIG_UNIX_DONTROUTE
790
  int one = 1;
791
  if (s->ttl == 1 && setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
792
    return "SO_DONTROUTE";
793
#endif 
794 828
#endif
795 829
  return NULL;
796 830
}
......
801 835
static char *
802 836
sk_setup(sock *s)
803 837
{
838
  int one = 1;
804 839
  int fd = s->fd;
805 840
  char *err = NULL;
806 841

  
......
809 844
  if (s->type == SK_UNIX)
810 845
    return NULL;
811 846

  
847
  if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
848
    s->flags |= SKF_PKTINFO;
849

  
850
#ifdef CONFIG_USE_HDRINCL
851
  if ((s->type == SK_IP) && (s->flags & SKF_PKTINFO))
852
  {
853
    s->flags &= ~SKF_PKTINFO;
854
    s->flags |= SKF_HDRINCL;
855
    if (setsockopt(fd, SOL_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
856
      ERR("IP_HDRINCL");
857
  }
858
#endif
859

  
860
  if (s->iface)
861
  {
862
#ifdef SO_BINDTODEVICE
863
    struct ifreq ifr;
864
    strcpy(ifr.ifr_name, s->iface->name);
865
    if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
866
      ERR("SO_BINDTODEVICE");
867
#endif
868

  
869
#ifdef CONFIG_UNIX_DONTROUTE
870
    if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
871
      ERR("SO_DONTROUTE");
872
#endif
873
  }
874

  
875
  if ((s->ttl >= 0) && (err = sk_set_ttl_int(s)))
876
    goto bad;
877

  
878
  if (err = sysio_register_cmsgs(s))
879
    goto bad;
880

  
881

  
812 882
#ifdef IPV6
813 883
  if ((s->tos >= 0) && setsockopt(fd, SOL_IPV6, IPV6_TCLASS, &s->tos, sizeof(s->tos)) < 0)
814 884
    WARN("IPV6_TCLASS");
......
821 891
    sk_set_priority(s, s->priority);
822 892

  
823 893
#ifdef IPV6
824
  int v = 1;
825
  if ((s->flags & SKF_V6ONLY) && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v)) < 0)
894
  if ((s->flags & SKF_V6ONLY) && setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0)
826 895
    WARN("IPV6_V6ONLY");
827 896
#endif
828 897

  
829
  if ((s->ttl >= 0) && (err = sk_set_ttl_int(s)))
830
    goto bad;
831

  
832
  err = sysio_register_cmsgs(s);
833 898
bad:
834 899
  return err;
835 900
}
......
926 991
int
927 992
sk_set_ipv6_checksum(sock *s, int offset)
928 993
{
929
  if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
994
  if (setsockopt(s->fd, SOL_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
930 995
    {
931 996
      log(L_ERR "sk_set_ipv6_checksum: IPV6_CHECKSUM: %m");
932 997
      return -1;
......
945 1010
  ICMP6_FILTER_SETPASS(p1, &f);
946 1011
  ICMP6_FILTER_SETPASS(p2, &f);
947 1012

  
948
  if (setsockopt(s->fd, IPPROTO_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
1013
  if (setsockopt(s->fd, SOL_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
949 1014
    {
950 1015
      log(L_ERR "sk_setup_icmp_filter: ICMP6_FILTER: %m");
951 1016
      return -1;
......
961 1026
  int zero = 0;
962 1027
  int index;
963 1028

  
964
  ASSERT(s->iface && s->iface->addr);
1029
  ASSERT(s->iface);
965 1030

  
966 1031
  index = s->iface->index;
967 1032
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
......
971 1036
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
972 1037
    ERR("IPV6_MULTICAST_IF");
973 1038

  
974
  if (err = sysio_bind_to_iface(s))
975
    goto bad;
976

  
977 1039
  return 0;
978 1040

  
979 1041
bad:
......
981 1043
  return -1;
982 1044
}
983 1045

  
1046
#ifdef CONFIG_IPV6_GLIBC_20
1047
#define ipv6mr_interface ipv6mr_ifindex
1048
#endif
1049

  
984 1050
int
985 1051
sk_join_group(sock *s, ip_addr maddr)
986 1052
{
987 1053
  struct ipv6_mreq mreq;
988 1054

  
989 1055
  set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
990

  
991
#ifdef CONFIG_IPV6_GLIBC_20
992
  mreq.ipv6mr_ifindex = s->iface->index;
993
#else
994 1056
  mreq.ipv6mr_interface = s->iface->index;
995
#endif
996 1057

  
997 1058
  if (setsockopt(s->fd, SOL_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
998 1059
    {
......
1009 1070
  struct ipv6_mreq mreq;
1010 1071
	
1011 1072
  set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
1012

  
1013
#ifdef CONFIG_IPV6_GLIBC_20
1014
  mreq.ipv6mr_ifindex = s->iface->index;
1015
#else
1016 1073
  mreq.ipv6mr_interface = s->iface->index;
1017
#endif
1018 1074

  
1019 1075
  if (setsockopt(s->fd, SOL_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) < 0)
1020 1076
    {
......
1032 1088
{
1033 1089
  char *err;
1034 1090

  
1035
  ASSERT(s->iface && s->iface->addr);
1091
  ASSERT(s->iface);
1036 1092

  
1037 1093
  if (err = sysio_setup_multicast(s))
1038 1094
    {
......
1142 1198
sk_open(sock *s)
1143 1199
{
1144 1200
  int fd;
1145
  sockaddr sa;
1146 1201
  int one = 1;
1147
  int type = s->type;
1148
  int has_src = ipa_nonzero(s->saddr) || s->sport;
1202
  int do_bind = 0;
1203
  int bind_port = 0;
1204
  ip_addr bind_addr = IPA_NONE;
1205
  sockaddr sa;
1149 1206
  char *err;
1150 1207

  
1151
  switch (type)
1208
  switch (s->type)
1152 1209
    {
1153 1210
    case SK_TCP_ACTIVE:
1154 1211
      s->ttx = "";			/* Force s->ttx != s->tpos */
1155 1212
      /* Fall thru */
1156 1213
    case SK_TCP_PASSIVE:
1157 1214
      fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
1215
      bind_port = s->sport;
1216
      bind_addr = s->saddr;
1217
      do_bind = bind_port || ipa_nonzero(bind_addr);
1158 1218
      break;
1219

  
1159 1220
    case SK_UDP:
1160 1221
      fd = socket(BIRD_PF, SOCK_DGRAM, IPPROTO_UDP);
1222
      bind_port = s->sport;
1223
      bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1224
      do_bind = 1;
1161 1225
      break;
1226

  
1162 1227
    case SK_IP:
1163 1228
      fd = socket(BIRD_PF, SOCK_RAW, s->dport);
1229
      bind_port = 0;
1230
      bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1231
      do_bind = ipa_nonzero(bind_addr);
1164 1232
      break;
1233

  
1165 1234
    case SK_MAGIC:
1166 1235
      fd = s->fd;
1167 1236
      break;
1237

  
1168 1238
    default:
1169
      bug("sk_open() called for invalid sock type %d", type);
1239
      bug("sk_open() called for invalid sock type %d", s->type);
1170 1240
    }
1171 1241
  if (fd < 0)
1172 1242
    die("sk_open: socket: %m");
......
1175 1245
  if (err = sk_setup(s))
1176 1246
    goto bad;
1177 1247

  
1178
  if (has_src)
1248
  if (do_bind)
1179 1249
    {
1180
      int port;
1181

  
1182
      if (type == SK_IP)
1183
	port = 0;
1184
      else
1250
      if (bind_port)
1185 1251
	{
1186
	  port = s->sport;
1187 1252
	  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
1188 1253
	    ERR("SO_REUSEADDR");
1189
	
1254

  
1190 1255
#ifdef CONFIG_NO_IFACE_BIND
1191 1256
	  /* Workaround missing ability to bind to an iface */
1192
	  if ((type == SK_UDP) && s->iface && ipa_zero(s->saddr))
1257
	  if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
1193 1258
	  {
1194 1259
	    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
1195 1260
	      ERR("SO_REUSEPORT");
1196 1261
	  }
1197 1262
#endif
1198 1263
	}
1199
      fill_in_sockaddr(&sa, s->saddr, s->iface, port);
1264

  
1265
      fill_in_sockaddr(&sa, bind_addr, s->iface, bind_port);
1200 1266
      if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
1201 1267
	ERR("bind");
1202 1268
    }
1269

  
1203 1270
  fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
1204 1271

  
1205 1272
  if (s->password)
......
1209 1276
	goto bad_no_log;
1210 1277
    }
1211 1278

  
1212
  switch (type)
1279
  switch (s->type)
1213 1280
    {
1214 1281
    case SK_TCP_ACTIVE:
1215 1282
      if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
......
1287 1354
  die("Unable to create control socket %s", name);
1288 1355
}
1289 1356

  
1357

  
1358
static inline int
1359
sk_sendmsg(sock *s)
1360
{
1361
  struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
1362
  byte cmsg_buf[CMSG_TX_SPACE];
1363
  sockaddr dst;
1364

  
1365
  fill_in_sockaddr(&dst, s->daddr, s->iface, s->dport);
1366

  
1367
  struct msghdr msg = {
1368
    .msg_name = &dst,
1369
    .msg_namelen = sizeof(dst),
1370
    .msg_iov = &iov,
1371
    .msg_iovlen = 1
1372
  };
1373

  
1374
#ifdef CONFIG_USE_HDRINCL
1375
  byte hdr[20];
1376
  struct iovec iov2[2] = { {hdr, 20}, iov };
1377

  
1378
  if (s->flags & SKF_HDRINCL)
1379
  {
1380
    fill_ip_header(s, hdr, iov.iov_len);
1381
    msg.msg_iov = iov2;
1382
    msg.msg_iovlen = 2;
1383
  }
1384
#endif
1385

  
1386
  if (s->flags & SKF_PKTINFO)
1387
    sysio_prepare_tx_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
1388

  
1389
  return sendmsg(s->fd, &msg, 0);
1390
}
1391

  
1392
static inline int
1393
sk_recvmsg(sock *s)
1394
{
1395
  struct iovec iov = {s->rbuf, s->rbsize};
1396
  byte cmsg_buf[CMSG_RX_SPACE];
1397
  sockaddr src;
1398

  
1399
  struct msghdr msg = {
1400
    .msg_name = &src,
1401
    .msg_namelen = sizeof(src),
1402
    .msg_iov = &iov,
1403
    .msg_iovlen = 1,
1404
    .msg_control = cmsg_buf,
1405
    .msg_controllen = sizeof(cmsg_buf),
1406
    .msg_flags = 0
1407
  };
1408

  
1409
  int rv = recvmsg(s->fd, &msg, 0);
1410
  if (rv < 0)
1411
    return rv;
1412

  
1413
  //ifdef IPV4
1414
  //  if (cf_type == SK_IP)
1415
  //    rv = ipv4_skip_header(pbuf, rv);
1416
  //endif
1417

  
1418
  get_sockaddr(&src, &s->faddr, NULL, &s->fport, 1);
1419
  sysio_process_rx_cmsgs(s, &msg);
1420

  
1421
  if (msg.msg_flags & MSG_TRUNC)
1422
    s->flags |= SKF_TRUNCATED;
1423
  else
1424
    s->flags &= ~SKF_TRUNCATED;
1425

  
1426
  return rv;
1427
}
1428

  
1429

  
1290 1430
static inline void reset_tx_buffer(sock *s) { s->ttx = s->tpos = s->tbuf; }
1291 1431

  
1292 1432
static int
......
1323 1463
	if (s->tbuf == s->tpos)
1324 1464
	  return 1;
1325 1465

  
1326
	sockaddr sa;
1327
	fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
1328

  
1329
	struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
1330
	// byte cmsg_buf[CMSG_TX_SPACE];
1331

  
1332
	struct msghdr msg = {
1333
	  .msg_name = &sa,
1334
	  .msg_namelen = sizeof(sa),
1335
	  .msg_iov = &iov,
1336
	  .msg_iovlen = 1};
1337

  
1338
	// sysio_prepare_tx_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
1339
	e = sendmsg(s->fd, &msg, 0);
1466
	e = sk_sendmsg(s);
1340 1467

  
1341 1468
	if (e < 0)
1342 1469
	  {
......
1346 1473
		s->err_hook(s, errno);
1347 1474
		return -1;
1348 1475
	      }
1476

  
1477
	    if (!s->tx_hook)
1478
	      reset_tx_buffer(s);
1349 1479
	    return 0;
1350 1480
	  }
1351 1481
	reset_tx_buffer(s);
......
1408 1538
 *
1409 1539
 * This is a sk_send() replacement for connection-less packet sockets
1410 1540
 * which allows destination of the packet to be chosen dynamically.
1541
 * Raw IP sockets should use 0 for @port.
1411 1542
 */
1412 1543
int
1413 1544
sk_send_to(sock *s, unsigned len, ip_addr addr, unsigned port)
1414 1545
{
1415 1546
  s->daddr = addr;
1416
  s->dport = port;
1547
  if (port)
1548
    s->dport = port;
1549

  
1417 1550
  s->ttx = s->tbuf;
1418 1551
  s->tpos = s->tbuf + len;
1419 1552
  return sk_maybe_write(s);
......
1480 1613
      return s->rx_hook(s, 0);
1481 1614
    default:
1482 1615
      {
1483
	sockaddr sa;
1484 1616
	int e;
1485 1617

  
1486
	struct iovec iov = {s->rbuf, s->rbsize};
1487
	byte cmsg_buf[CMSG_RX_SPACE];
1488

  
1489
	struct msghdr msg = {
1490
	  .msg_name = &sa,
1491
	  .msg_namelen = sizeof(sa),
1492
	  .msg_iov = &iov,
1493
	  .msg_iovlen = 1,
1494
	  .msg_control = cmsg_buf,
1495
	  .msg_controllen = sizeof(cmsg_buf),
1496
	  .msg_flags = 0};
1497

  
1498
	e = recvmsg(s->fd, &msg, 0);
1618
	e = sk_recvmsg(s);
1499 1619

  
1500 1620
	if (e < 0)
1501 1621
	  {
......
1503 1623
	      s->err_hook(s, errno);
1504 1624
	    return 0;
1505 1625
	  }
1506
	s->rpos = s->rbuf + e;
1507
	get_sockaddr(&sa, &s->faddr, NULL, &s->fport, 1);
1508
	sysio_process_rx_cmsgs(s, &msg);
1509 1626

  
1627
	s->rpos = s->rbuf + e;
1510 1628
	s->rx_hook(s, e);
1511 1629
	return 1;
1512 1630
      }

Also available in: Unified diff