network: DHCP server Add support to transmit SIP server
authorSusant Sahani <ssahani@vmware.com>
Wed, 18 Sep 2019 13:22:47 +0000 (15:22 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 20 Sep 2019 12:22:23 +0000 (21:22 +0900)
1. DHCP server trasmit
2. Client parses and saves in leases
Implements http://www.rfc-editor.org/rfc/rfc3361.txt

```
Frame 134: 348 bytes on wire (2784 bits), 348 bytes captured (2784 bits) on interface 0
Ethernet II, Src: 42:65:85:d6:4e:32 (42:65:85:d6:4e:32), Dst: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4)
Internet Protocol Version 4, Src: 192.168.5.1, Dst: 192.168.5.11
User Datagram Protocol, Src Port: 67, Dst Port: 68
Dynamic Host Configuration Protocol (ACK)
    Message type: Boot Reply (2)
    Hardware type: Ethernet (0x01)
    Hardware address length: 6
    Hops: 0
    Transaction ID: 0x7cc87cb4
    Seconds elapsed: 0
    Bootp flags: 0x0000 (Unicast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 192.168.5.11
    Next server IP address: 0.0.0.0
    Relay agent IP address: 0.0.0.0
    Client MAC address: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4)
    Client hardware address padding: 00000000000000000000
    Server host name not given
    Boot file name not given
    Magic cookie: DHCP
    Option: (53) DHCP Message Type (ACK)
        Length: 1
        DHCP: ACK (5)
    Option: (51) IP Address Lease Time
        Length: 4
        IP Address Lease Time: (3600s) 1 hour
    Option: (1) Subnet Mask (255.255.255.0)
        Length: 4
        Subnet Mask: 255.255.255.0
    Option: (3) Router
        Length: 4
        Router: 192.168.5.1
    Option: (6) Domain Name Server
        Length: 4
        Domain Name Server: 192.168.5.1
    Option: (42) Network Time Protocol Servers
        Length: 4
        Network Time Protocol Server: 192.168.1.1
    Option: (120) SIP Servers <=====here
        Length: 9
        SIP Server Encoding: IPv4 Address (1)
        SIP Server Address: 192.168.1.1
        SIP Server Address: 192.168.5.2
    Option: (101) TCode
        Length: 13
        TZ TCode: Europe/Berlin
    Option: (54) DHCP Server Identifier (192.168.5.1)
        Length: 4
        DHCP Server Identifier: 192.168.5.1
    Option: (255) End
        Option End: 255
```

```
cat /run/systemd/netif/state                                                                                                   ✔  ⚡  3148  16:40:51
OPER_STATE=routable
CARRIER_STATE=carrier
ADDRESS_STATE=routable
DNS=192.168.94.2 192.168.5.1
NTP=192.168.5.1
SIP=192.168.1.1 192.168.5.2

```

aa

22 files changed:
man/systemd.network.xml
src/libsystemd-network/dhcp-lease-internal.h
src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/sd-dhcp-lease.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd/sd-network/sd-network.c
src/network/networkd-dhcp-common.c
src/network/networkd-dhcp-common.h
src/network/networkd-dhcp-server.c
src/network/networkd-dhcp-server.h
src/network/networkd-dhcp4.c
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/systemd/sd-dhcp-client.h
src/systemd/sd-dhcp-lease.h
src/systemd/sd-dhcp-server.h
src/systemd/sd-network.h
test/fuzz/fuzz-network-parser/directives.network

index 0fbc4df..5850410 100644 (file)
           </listitem>
         </varlistentry>
         <varlistentry>
+          <term><varname>UseSIP=</varname></term>
+          <listitem>
+            <para>When true (the default), the SIP servers received
+            from the DHCP server will be saved at the state files and can be
+            read via <function>sd_network_link_get_sip_servers()</function> function.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
           <term><varname>UseMTU=</varname></term>
           <listitem>
             <para>When true, the interface maximum transmission unit
       </varlistentry>
 
       <varlistentry>
+        <term><varname>EmitSIP=</varname></term>
+        <term><varname>SIP=</varname></term>
+
+        <listitem><para>Similar to the <varname>EmitDNS=</varname> and
+        <varname>DNS=</varname> settings described above, these
+        settings configure whether and what SIP server information
+        shall be emitted as part of the DHCP lease. The same syntax,
+        propagation semantics and defaults apply as for
+        <varname>EmitDNS=</varname> and
+        <varname>DNS=</varname>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><varname>EmitRouter=</varname></term>
 
         <listitem><para>Similar to the <varname>EmitDNS=</varname>
index 122042a..a2d0f8b 100644 (file)
@@ -58,6 +58,9 @@ struct sd_dhcp_lease {
         struct in_addr *ntp;
         size_t ntp_size;
 
+        struct in_addr *sip;
+        size_t sip_size;
+
         struct sd_dhcp_route *static_route;
         size_t static_route_size, static_route_allocated;
 
index 05386b6..d2f1f5d 100644 (file)
@@ -65,6 +65,18 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
 
                 break;
         }
+        case SD_DHCP_OPTION_SIP_SERVER:
+                if (*offset + 3 + optlen > size)
+                        return -ENOBUFS;
+
+                options[*offset] = code;
+                options[*offset + 1] = optlen + 1;
+                options[*offset + 2] = 1;
+
+                memcpy_safe(&options[*offset + 3], optval, optlen);
+                *offset += 3 + optlen;
+
+                break;
         default:
                 if (*offset + 2 + optlen > size)
                         return -ENOBUFS;
index 256006e..0a64082 100644 (file)
@@ -45,8 +45,8 @@ struct sd_dhcp_server {
 
         char *timezone;
 
-        struct in_addr *ntp, *dns;
-        unsigned n_ntp, n_dns;
+        struct in_addr *ntp, *dns, *sip;
+        unsigned n_ntp, n_dns, n_sip;
 
         bool emit_router;
 
index 17b2bb7..e360b72 100644 (file)
@@ -120,6 +120,17 @@ int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
         return (int) lease->ntp_size;
 }
 
+int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
+        assert_return(lease, -EINVAL);
+        assert_return(addr, -EINVAL);
+
+        if (lease->sip_size <= 0)
+                return -ENODATA;
+
+        *addr = lease->sip;
+        return (int) lease->sip_size;
+}
+
 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
         assert_return(lease, -EINVAL);
         assert_return(domainname, -EINVAL);
@@ -269,6 +280,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
         free(lease->domainname);
         free(lease->dns);
         free(lease->ntp);
+        free(lease->sip);
         free(lease->static_route);
         free(lease->client_id);
         free(lease->vendor_specific);
@@ -402,6 +414,36 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
         return 0;
 }
 
+static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
+        assert(option);
+        assert(ret);
+        assert(n_ret);
+
+        if (len <= 0) {
+                *ret = mfree(*ret);
+                *n_ret = 0;
+        } else {
+                size_t n_addresses;
+                struct in_addr *addresses;
+                int l = len - 1;
+
+                if (l % 4 != 0)
+                        return -EINVAL;
+
+                n_addresses = l / 4;
+
+                addresses = newdup(struct in_addr, option + 1, n_addresses);
+                if (!addresses)
+                        return -ENOMEM;
+
+                free(*ret);
+                *ret = addresses;
+                *n_ret = n_addresses;
+        }
+
+        return 0;
+}
+
 static int lease_parse_routes(
                 const uint8_t *option, size_t len,
                 struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) {
@@ -555,6 +597,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                         log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
                 break;
 
+        case SD_DHCP_OPTION_SIP_SERVER:
+                r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
+                break;
+
         case SD_DHCP_OPTION_STATIC_ROUTE:
                 r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
                 if (r < 0)
@@ -893,6 +941,13 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
                 fputc('\n', f);
         }
 
+        r = sd_dhcp_lease_get_sip(lease, &addresses);
+        if (r > 0) {
+                fputs("SIP=", f);
+                serialize_in_addrs(f, addresses, r, false, NULL);
+                fputc('\n', f);
+        }
+
         r = sd_dhcp_lease_get_domainname(lease, &string);
         if (r >= 0)
                 fprintf(f, "DOMAINNAME=%s\n", string);
@@ -983,6 +1038,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                 *broadcast = NULL,
                 *dns = NULL,
                 *ntp = NULL,
+                *sip = NULL,
                 *mtu = NULL,
                 *routes = NULL,
                 *domains = NULL,
@@ -1011,6 +1067,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                            "BROADCAST", &broadcast,
                            "DNS", &dns,
                            "NTP", &ntp,
+                           "SIP", &sip,
                            "MTU", &mtu,
                            "DOMAINNAME", &lease->domainname,
                            "HOSTNAME", &lease->hostname,
@@ -1115,6 +1172,14 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         lease->ntp_size = r;
         }
 
+        if (sip) {
+                r = deserialize_in_addrs(&lease->sip, sip);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", ntp);
+                else
+                        lease->ntp_size = r;
+        }
+
         if (mtu) {
                 r = safe_atou16(mtu, &lease->mtu);
                 if (r < 0)
index 7cb44d1..13f104f 100644 (file)
@@ -139,6 +139,7 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
         free(server->timezone);
         free(server->dns);
         free(server->ntp);
+        free(server->sip);
 
         hashmap_free(server->leases_by_client_id);
 
@@ -498,6 +499,15 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
                         return r;
         }
 
+        if (server->n_sip > 0) {
+                r = dhcp_option_append(
+                                &packet->dhcp, req->max_optlen, &offset, 0,
+                                SD_DHCP_OPTION_SIP_SERVER,
+                                sizeof(struct in_addr) * server->n_sip, server->sip);
+                if (r < 0)
+                        return r;
+        }
+
         if (server->timezone) {
                 r = dhcp_option_append(
                                 &packet->dhcp, req->max_optlen, &offset, 0,
@@ -1124,6 +1134,32 @@ int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], u
         return 1;
 }
 
+int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n) {
+        assert_return(server, -EINVAL);
+        assert_return(sip || n <= 0, -EINVAL);
+
+        if (server->n_sip == n &&
+            memcmp(server->sip, sip, sizeof(struct in_addr) * n) == 0)
+                return 0;
+
+        if (n <= 0) {
+                server->sip = mfree(server->sip);
+                server->n_sip = 0;
+        } else {
+                struct in_addr *c;
+
+                c = newdup(struct in_addr, sip, n);
+                if (!c)
+                        return -ENOMEM;
+
+                free(server->sip);
+                server->sip = c;
+                server->n_sip = n;
+        }
+
+        return 1;
+}
+
 int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
         assert_return(server, -EINVAL);
 
index 8ff9382..bdd891d 100644 (file)
@@ -249,6 +249,10 @@ _public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) {
         return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
 }
 
+_public_ int sd_network_link_get_sip_servers(int ifindex, char ***ret) {
+        return network_link_get_strv(ifindex, "SIP", ret);
+}
+
 _public_ int sd_network_link_get_dns_default_route(int ifindex) {
         char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
         _cleanup_free_ char *s = NULL;
index 626b975..36ae728 100644 (file)
@@ -91,6 +91,38 @@ int config_parse_dhcp_use_dns(
         return 0;
 }
 
+int config_parse_dhcp_use_sip(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse UseSIP=%s, ignoring assignment: %m", rvalue);
+                return 0;
+        }
+
+        network->dhcp_use_sip = r;
+
+        return 0;
+}
+
 int config_parse_dhcp_use_ntp(
                 const char* unit,
                 const char *filename,
index c5af0be..3e079b9 100644 (file)
@@ -31,5 +31,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_sip);
 CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
 CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
index f4c2178..efb82d7 100644 (file)
@@ -137,6 +137,55 @@ static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
         return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
 }
 
+static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+        _cleanup_free_ struct in_addr *addresses = NULL;
+        size_t n_addresses = 0, n_allocated = 0;
+        char **a;
+
+        if (!link->network)
+                return 0;
+
+        log_debug("Copying SIP server information from %s", link->ifname);
+
+        STRV_FOREACH(a, link->network->sip) {
+                union in_addr_union ia;
+
+                /* Only look for IPv4 addresses */
+                if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
+                        continue;
+
+                /* Never propagate obviously borked data */
+                if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
+                        continue;
+
+                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+                        return log_oom();
+
+                addresses[n_addresses++] = ia.in;
+        }
+
+        if (link->network->dhcp_use_sip && link->dhcp_lease) {
+                const struct in_addr *da = NULL;
+                int j, n;
+
+                n = sd_dhcp_lease_get_sip(link->dhcp_lease, &da);
+                if (n > 0) {
+
+                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+                                return log_oom();
+
+                        for (j = 0; j < n; j++)
+                                if (in4_addr_is_non_local(&da[j]))
+                                        addresses[n_addresses++] = da[j];
+                }
+        }
+
+        if (n_addresses <= 0)
+                return 0;
+
+        return sd_dhcp_server_set_sip(s, addresses, n_addresses);
+}
+
 int dhcp4_server_configure(Link *link) {
         Address *address;
         Link *uplink = NULL;
@@ -209,6 +258,24 @@ int dhcp4_server_configure(Link *link) {
                         log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
         }
 
+        if (link->network->dhcp_server_emit_sip) {
+                if (link->network->n_dhcp_server_sip > 0)
+                        r = sd_dhcp_server_set_sip(link->dhcp_server, link->network->dhcp_server_sip, link->network->n_dhcp_server_sip);
+                else {
+                        if (!acquired_uplink)
+                                uplink = manager_find_uplink(link->manager, link);
+
+                        if (!uplink) {
+                                log_link_debug(link, "Not emitting sip server information on link, couldn't find suitable uplink.");
+                                r = 0;
+                        } else
+                                r = link_push_uplink_sip_to_dhcp_server(uplink, link->dhcp_server);
+
+                }
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Failed to set SIP server for DHCP server, ignoring: %m");
+        }
+
         r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m");
@@ -345,3 +412,55 @@ int config_parse_dhcp_server_ntp(
                 n->dhcp_server_ntp = m;
         }
 }
+
+int config_parse_dhcp_server_sip(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *n = data;
+        const char *p = rvalue;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+                union in_addr_union a;
+                struct in_addr *m;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to extract word, ignoring: %s", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse SIP server address '%s', ignoring: %m", w);
+                        continue;
+                }
+
+                m = reallocarray(n->dhcp_server_sip, n->n_dhcp_server_sip + 1, sizeof(struct in_addr));
+                if (!m)
+                        return log_oom();
+
+                m[n->n_dhcp_server_sip++] = a.in;
+                n->dhcp_server_sip = m;
+        }
+}
index e97e56b..7c12538 100644 (file)
@@ -9,3 +9,4 @@ int dhcp4_server_configure(Link *link);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
index 01fe769..06e8719 100644 (file)
@@ -1159,6 +1159,12 @@ int dhcp4_configure(Link *link) {
                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
         }
 
+        if (link->network->dhcp_use_sip) {
+                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_SIP_SERVER);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for SIP server: %m");
+        }
+
         if (link->network->dhcp_use_timezone) {
                 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
                 if (r < 0)
index be7e311..50648b2 100644 (file)
@@ -3597,6 +3597,22 @@ int link_save(Link *link) {
                                         space = true;
                 }
 
+                fputc('\n', f);
+
+                fputs("SIP=", f);
+                space = false;
+                fputstrv(f, link->network->sip, NULL, &space);
+
+                if (link->network->dhcp_use_sip &&
+                    link->dhcp_lease) {
+                        const struct in_addr *addresses;
+
+                        r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
+                        if (r > 0)
+                                if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0)
+                                        space = true;
+                }
+
                 if (link->network->dhcp6_use_ntp && dhcp6_lease) {
                         struct in6_addr *in6_addrs;
                         char **hosts;
index ea962e5..e0c095d 100644 (file)
@@ -1333,16 +1333,16 @@ static int ordered_set_put_in4_addrv(OrderedSet *s,
 }
 
 static int manager_save(Manager *m) {
-        _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL;
-        Link *link;
-        Iterator i;
-        _cleanup_free_ char *temp_path = NULL;
-        _cleanup_strv_free_ char **p = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
+        const char *operstate_str, *carrier_state_str, *address_state_str;
         LinkOperationalState operstate = LINK_OPERSTATE_OFF;
         LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
         LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
-        const char *operstate_str, *carrier_state_str, *address_state_str;
+        _cleanup_free_ char *temp_path = NULL;
+        _cleanup_strv_free_ char **p = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        Link *link;
+        Iterator i;
         int r;
 
         assert(m);
@@ -1357,6 +1357,10 @@ static int manager_save(Manager *m) {
         if (!ntp)
                 return -ENOMEM;
 
+       sip = ordered_set_new(&string_hash_ops);
+       if (!sip)
+                return -ENOMEM;
+
         search_domains = ordered_set_new(&dns_name_hash_ops);
         if (!search_domains)
                 return -ENOMEM;
@@ -1426,6 +1430,18 @@ static int manager_save(Manager *m) {
                                 return r;
                 }
 
+                if (link->network->dhcp_use_sip) {
+                        const struct in_addr *addresses;
+
+                        r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
+                        if (r > 0) {
+                                r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
+                                if (r < 0)
+                                        return r;
+                        } else if (r < 0 && r != -ENODATA)
+                                return r;
+                }
+
                 if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
                         const char *domainname;
                         char **domains = NULL;
@@ -1476,6 +1492,7 @@ static int manager_save(Manager *m) {
 
         ordered_set_print(f, "DNS=", dns);
         ordered_set_print(f, "NTP=", ntp);
+        ordered_set_print(f, "SIP=", sip);
         ordered_set_print(f, "DOMAINS=", search_domains);
         ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
 
index 8772b0e..11e541e 100644 (file)
@@ -145,6 +145,7 @@ DHCPv4.ClientIdentifier,                config_parse_dhcp_client_identifier,
 DHCPv4.UseDNS,                          config_parse_bool,                               0,                             offsetof(Network, dhcp_use_dns)
 DHCPv4.RoutesToDNS,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_routes_to_dns)
 DHCPv4.UseNTP,                          config_parse_bool,                               0,                             offsetof(Network, dhcp_use_ntp)
+DHCPv4.UseSIP,                          config_parse_bool,                               0,                             offsetof(Network, dhcp_use_sip)
 DHCPv4.UseMTU,                          config_parse_bool,                               0,                             offsetof(Network, dhcp_use_mtu)
 DHCPv4.UseHostname,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_use_hostname)
 DHCPv4.UseDomains,                      config_parse_dhcp_use_domains,                   0,                             offsetof(Network, dhcp_use_domains)
@@ -182,6 +183,8 @@ DHCPServer.EmitDNS,                     config_parse_bool,
 DHCPServer.DNS,                         config_parse_dhcp_server_dns,                    0,                             0
 DHCPServer.EmitNTP,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server_emit_ntp)
 DHCPServer.NTP,                         config_parse_dhcp_server_ntp,                    0,                             0
+DHCPServer.EmitSIP,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server_emit_sip)
+DHCPServer.SIP,                         config_parse_dhcp_server_sip,                    0,                             0
 DHCPServer.EmitRouter,                  config_parse_bool,                               0,                             offsetof(Network, dhcp_server_emit_router)
 DHCPServer.EmitTimezone,                config_parse_bool,                               0,                             offsetof(Network, dhcp_server_emit_timezone)
 DHCPServer.Timezone,                    config_parse_timezone,                           0,                             offsetof(Network, dhcp_server_timezone)
index 2fe4c2d..3ea5654 100644 (file)
@@ -363,6 +363,7 @@ int network_load_one(Manager *manager, const char *filename) {
                 .dhcp = ADDRESS_FAMILY_NO,
                 .dhcp_critical = -1,
                 .dhcp_use_ntp = true,
+                .dhcp_use_sip = true,
                 .dhcp_use_dns = true,
                 .dhcp_use_hostname = true,
                 .dhcp_use_routes = true,
@@ -386,6 +387,7 @@ int network_load_one(Manager *manager, const char *filename) {
 
                 .dhcp_server_emit_dns = true,
                 .dhcp_server_emit_ntp = true,
+                .dhcp_server_emit_sip = true,
                 .dhcp_server_emit_router = true,
                 .dhcp_server_emit_timezone = true,
 
@@ -546,6 +548,8 @@ static Network *network_free(Network *network) {
 
         strv_free(network->ntp);
         free(network->dns);
+        strv_free(network->sip);
+        free(network->sip);
         ordered_set_free_free(network->search_domains);
         ordered_set_free_free(network->route_domains);
         strv_free(network->bind_carrier);
@@ -608,6 +612,7 @@ static Network *network_free(Network *network) {
         free(network->dhcp_server_timezone);
         free(network->dhcp_server_dns);
         free(network->dhcp_server_ntp);
+        free(network->dhcp_server_sip);
 
         set_free_free(network->dnssec_negative_trust_anchors);
 
index 3bb21ef..837206a 100644 (file)
@@ -93,6 +93,7 @@ struct Network {
         bool dhcp_use_dns;
         bool dhcp_routes_to_dns;
         bool dhcp_use_ntp;
+        bool dhcp_use_sip;
         bool dhcp_use_mtu;
         bool dhcp_use_routes;
         bool dhcp_use_timezone;
@@ -110,12 +111,19 @@ struct Network {
 
         /* DHCP Server Support */
         bool dhcp_server;
+
         bool dhcp_server_emit_dns;
         struct in_addr *dhcp_server_dns;
         unsigned n_dhcp_server_dns;
+
         bool dhcp_server_emit_ntp;
         struct in_addr *dhcp_server_ntp;
         unsigned n_dhcp_server_ntp;
+
+        bool dhcp_server_emit_sip;
+        struct in_addr *dhcp_server_sip;
+        unsigned n_dhcp_server_sip;
+
         bool dhcp_server_emit_router;
         bool dhcp_server_emit_timezone;
         char *dhcp_server_timezone;
@@ -257,6 +265,7 @@ struct Network {
         Set *dnssec_negative_trust_anchors;
 
         char **ntp;
+        char **sip;
         char **bind_carrier;
 };
 
index ab62368..46209cd 100644 (file)
@@ -87,6 +87,7 @@ enum {
         SD_DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
         SD_DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
         SD_DHCP_OPTION_DOMAIN_SEARCH_LIST          = 119,
+        SD_DHCP_OPTION_SIP_SERVER                  = 120,
         SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,
         SD_DHCP_OPTION_PRIVATE_BASE                = 224,
        /* Windows 10 option to send when Anonymize=true */
index d299c79..b80d607 100644 (file)
@@ -44,6 +44,7 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr);
 int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
 int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
 int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
 int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
index 2d5125d..2252a4a 100644 (file)
@@ -46,8 +46,9 @@ int sd_dhcp_server_stop(sd_dhcp_server *server);
 int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size);
 
 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone);
-int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n);
-int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr dns[], unsigned n);
+int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n);
+int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n);
+int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n);
 int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled);
 
 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t);
index 1cf4c2e..d0b4322 100644 (file)
@@ -160,6 +160,9 @@ int sd_network_link_get_search_domains(int ifindex, char ***domains);
 /* Get the route DNS domain names for a given link. */
 int sd_network_link_get_route_domains(int ifindex, char ***domains);
 
+/* Get the sip servers for a given link. */
+int sd_network_link_get_sip_servers(int ifindex, char ***sip);
+
 /* Get whether this link shall be used as 'default route' for DNS queries */
 int sd_network_link_get_dns_default_route(int ifindex);
 
index 0381d8d..3be6430 100644 (file)
@@ -72,6 +72,7 @@ UseRoutes=
 IAID=
 UserClass=
 UseNTP=
+UseSIP=
 UseMTU=
 UseDomainName=
 RouteMetric=
@@ -245,6 +246,8 @@ PoolOffset=
 Timezone=
 EmitDNS=
 NTP=
+EmitSIP=
+SIP=
 EmitRouter=
 MaxLeaseTimeSec=
 DefaultLeaseTimeSec=