int sk_setup_broadcast(sock *s);
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
-int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey);
+int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, char *passwd, int setkey);
int sk_set_ipv6_checksum(sock *s, int offset);
int sk_set_icmp6_filter(sock *s, int p1, int p2);
void sk_log_error(sock *s, const char *p);
{
if (p->cf->password)
{
+ ip_addr prefix = p->cf->remote_ip;
+ int pxlen = -1;
+
+ if (p->cf->remote_range)
+ {
+ prefix = net_prefix(p->cf->remote_range);
+ pxlen = net_pxlen(p->cf->remote_range);
+ }
+
int rv = sk_set_md5_auth(p->sock->sk,
- p->cf->local_ip, p->cf->remote_ip, p->cf->iface,
+ p->cf->local_ip, prefix, pxlen, p->cf->iface,
enable ? p->cf->password : NULL, p->cf->setkey);
if (rv < 0)
* operations to implement replace.
*/
static int
-setkey_md5(sockaddr *src, sockaddr *dst, uint pxlen, char *passwd, uint type)
+setkey_md5(sockaddr *src, uint slen, sockaddr *dst, uint dlen, char *passwd, uint type)
{
uint passwd_len = passwd ? strlen(passwd) : 0;
saddr->sadb_address_len = PFKEY_UNIT64(len);
saddr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
saddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
- saddr->sadb_address_prefixlen = pxlen;
+ saddr->sadb_address_prefixlen = slen;
memcpy(pos + sizeof(struct sadb_address), &src->sa, src->sa.sa_len);
pos += len;
daddr->sadb_address_len = PFKEY_UNIT64(len);
daddr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
daddr->sadb_address_proto = IPSEC_ULPROTO_ANY;
- daddr->sadb_address_prefixlen = pxlen;
+ daddr->sadb_address_prefixlen = dlen;
memcpy(pos + sizeof(struct sadb_address), &dst->sa, dst->sa.sa_len);
pos += len;
* Manipulation with the IPsec SA/SP database
*/
static int
-sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd)
+sk_set_md5_in_sasp_db(sock *s, ip_addr local, ip_addr remote, int pxlen, struct iface *ifa, char *passwd)
{
sockaddr src, dst;
sockaddr_fill(&src, s->af, local, ifa, 0);
sockaddr_fill(&dst, s->af, remote, ifa, 0);
- uint pxlen = (s->af == AF_INET) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
+ uint maxlen = (s->af == AF_INET) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
+ uint slen = maxlen;
+ uint dlen = (pxlen < 0) ? maxlen : pxlen;
if (passwd && *passwd)
{
if (len > TCP_KEYLEN_MAX)
ERR_MSG("The password for TCP MD5 Signature is too long");
- if ((setkey_md5(&src, &dst, pxlen, passwd, SADB_ADD) < 0) ||
- (setkey_md5(&dst, &src, pxlen, passwd, SADB_ADD) < 0))
+ if ((setkey_md5(&src, slen, &dst, dlen, passwd, SADB_ADD) < 0) ||
+ (setkey_md5(&dst, dlen, &src, slen, passwd, SADB_ADD) < 0))
ERR_MSG("Cannot add TCP-MD5 password into the IPsec SA/SP database");
}
else
{
- if ((setkey_md5(&src, &dst, pxlen, NULL, SADB_DELETE) < 0) ||
- (setkey_md5(&dst, &src, pxlen, NULL, SADB_DELETE) < 0))
+ if ((setkey_md5(&src, slen, &dst, dlen, NULL, SADB_DELETE) < 0) ||
+ (setkey_md5(&dst, dlen, &src, slen, NULL, SADB_DELETE) < 0))
ERR_MSG("Cannot delete TCP-MD5 password from the IPsec SA/SP database");
}
return 0;
#endif
int
-sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
+sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, int pxlen UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
{
#ifdef USE_MD5SIG_SETKEY
if (setkey)
- if (sk_set_md5_in_sasp_db(s, local, remote, ifa, passwd) < 0)
+ if (sk_set_md5_in_sasp_db(s, local, remote, pxlen, ifa, passwd) < 0)
return -1;
#endif
* Can be freely distributed and used under the terms of the GNU GPL.
*/
-
-#ifndef IP_MINTTL
-#define IP_MINTTL 21
-#endif
-
-#ifndef IPV6_TCLASS
-#define IPV6_TCLASS 67
-#endif
-
#ifndef IPV6_MINHOPCOUNT
#define IPV6_MINHOPCOUNT 73
#endif
+#ifndef TCP_MD5SIG_EXT
+#define TCP_MD5SIG_EXT 32
+#endif
-#ifndef TCP_MD5SIG
-
-#define TCP_MD5SIG 14
-#define TCP_MD5SIG_MAXKEYLEN 80
+#ifndef TCP_MD5SIG_FLAG_PREFIX
+#define TCP_MD5SIG_FLAG_PREFIX 1
+#endif
-struct tcp_md5sig {
- struct sockaddr_storage tcpm_addr; /* address associated */
- u16 __tcpm_pad1; /* zero */
- u16 tcpm_keylen; /* key length */
- u32 __tcpm_pad2; /* zero */
- u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
+/* We redefine the tcp_md5sig structure with different name to avoid collision with older headers */
+struct tcp_md5sig_ext {
+ struct sockaddr_storage tcpm_addr; /* Address associated */
+ u8 tcpm_flags; /* Extension flags */
+ u8 tcpm_prefixlen; /* Address prefix */
+ u16 tcpm_keylen; /* Key length */
+ u32 __tcpm_pad2; /* Zero */
+ u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* Key (binary) */
};
-#endif
-
/* Linux does not care if sa_len is larger than needed */
#define SA_LEN(x) sizeof(sockaddr)
*/
int
-sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED)
+sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, int pxlen, struct iface *ifa, char *passwd, int setkey UNUSED)
{
- struct tcp_md5sig md5;
+ struct tcp_md5sig_ext md5;
memset(&md5, 0, sizeof(md5));
sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
memcpy(&md5.tcpm_key, passwd, len);
}
- if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
+ if (pxlen < 0)
{
- if (errno == ENOPROTOOPT)
- ERR_MSG("Kernel does not support TCP MD5 signatures");
- else
- ERR("TCP_MD5SIG");
+ if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
+ if (errno == ENOPROTOOPT)
+ ERR_MSG("Kernel does not support TCP MD5 signatures");
+ else
+ ERR("TCP_MD5SIG");
+ }
+ else
+ {
+ md5.tcpm_flags = TCP_MD5SIG_FLAG_PREFIX;
+ md5.tcpm_prefixlen = pxlen;
+
+ if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG_EXT, &md5, sizeof(md5)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ ERR_MSG("Kernel does not support extended TCP MD5 signatures");
+ else
+ ERR("TCP_MD5SIG_EXT");
+ }
}
return 0;
}
if (s->password)
- if (sk_set_md5_auth(s, s->saddr, s->daddr, s->iface, s->password, 0) < 0)
+ if (sk_set_md5_auth(s, s->saddr, s->daddr, -1, s->iface, s->password, 0) < 0)
goto err;
switch (s->type)