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