1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_mdns_responder_sample, LOG_LEVEL_DBG);
9
10 #include <zephyr/kernel.h>
11
12 #include <zephyr/net/ethernet.h>
13
14 /* User data for the interface callback */
15 struct ud {
16 struct net_if *first;
17 struct net_if *second;
18 };
19
iface_cb(struct net_if * iface,void * user_data_param)20 static void iface_cb(struct net_if *iface, void *user_data_param)
21 {
22 struct ud *user_data = user_data_param;
23
24 if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
25 return;
26 }
27
28 if (!user_data->first) {
29 user_data->first = iface;
30 return;
31 }
32
33 if (!user_data->second) {
34 user_data->second = iface;
35 return;
36 }
37 }
38
setup_iface(struct net_if * eth_iface,struct net_if * iface,const char * ipv6_addr,const char * ipv4_addr,const char * netmask,uint16_t vlan_tag)39 static int setup_iface(struct net_if *eth_iface,
40 struct net_if *iface,
41 const char *ipv6_addr,
42 const char *ipv4_addr,
43 const char *netmask,
44 uint16_t vlan_tag)
45 {
46 struct net_if_addr *ifaddr;
47 struct in_addr addr4;
48 struct in6_addr addr6;
49 int ret;
50
51 ret = net_eth_vlan_enable(eth_iface, vlan_tag);
52 if (ret < 0) {
53 LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret);
54 }
55
56 if (IS_ENABLED(CONFIG_NET_IPV6)) {
57 if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
58 LOG_ERR("Invalid address: %s", ipv6_addr);
59 return -EINVAL;
60 }
61
62 ifaddr = net_if_ipv6_addr_add(iface, &addr6,
63 NET_ADDR_MANUAL, 0);
64 if (!ifaddr) {
65 LOG_ERR("Cannot add %s to interface %p",
66 ipv6_addr, iface);
67 return -EINVAL;
68 }
69 }
70
71 if (IS_ENABLED(CONFIG_NET_IPV4)) {
72 if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
73 LOG_ERR("Invalid address: %s", ipv4_addr);
74 return -EINVAL;
75 }
76
77 ifaddr = net_if_ipv4_addr_add(iface, &addr4,
78 NET_ADDR_MANUAL, 0);
79 if (!ifaddr) {
80 LOG_ERR("Cannot add %s to interface %p",
81 ipv4_addr, iface);
82 return -EINVAL;
83 }
84
85 if (netmask && netmask[0]) {
86 struct in_addr nm;
87
88 if (net_addr_pton(AF_INET, netmask, &nm)) {
89 LOG_ERR("Invalid netmask: %s", ipv4_addr);
90 return -EINVAL;
91 }
92
93 net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm);
94 }
95 }
96
97 LOG_DBG("Interface %p VLAN tag %d setup done.", iface, vlan_tag);
98
99 return 0;
100 }
101
init_vlan(void)102 int init_vlan(void)
103 {
104 struct net_if *iface;
105 struct ud user_data;
106 int ret;
107
108 iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
109 if (!iface) {
110 LOG_ERR("No ethernet interfaces found.");
111 return -ENOENT;
112 }
113
114 memset(&user_data, 0, sizeof(user_data));
115
116 net_if_foreach(iface_cb, &user_data);
117
118 /* This sample has two VLANs. For the second one we need to manually
119 * create IP address for this test. But first the VLAN needs to be
120 * added to the interface so that IPv6 DAD can work properly.
121 */
122 ret = setup_iface(iface, user_data.first,
123 CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
124 CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
125 CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK,
126 CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG);
127 if (ret < 0) {
128 return ret;
129 }
130
131 ret = setup_iface(iface, user_data.second,
132 CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR,
133 CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR,
134 CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_NETMASK,
135 CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG);
136 if (ret < 0) {
137 return ret;
138 }
139
140 /* Bring up the VLAN interface automatically */
141 net_if_up(user_data.first);
142 net_if_up(user_data.second);
143
144 return 0;
145 }
146