1import socket
2from pr2modules.common import map_namespace
3from pr2modules.netlink import nlmsg
4from pr2modules.netlink import nla
5
6# address attributes
7#
8# Important comment:
9# For IPv4, IFA_ADDRESS is a prefix address, not a local interface
10# address. It makes no difference for normal interfaces, but
11# for point-to-point ones IFA_ADDRESS means DESTINATION address,
12# and the local address is supplied in IFA_LOCAL attribute.
13#
14
15IFA_F_SECONDARY = 0x01
16# IFA_F_TEMPORARY IFA_F_SECONDARY
17IFA_F_NODAD = 0x02
18IFA_F_OPTIMISTIC = 0x04
19IFA_F_DADFAILED = 0x08
20IFA_F_HOMEADDRESS = 0x10
21IFA_F_DEPRECATED = 0x20
22IFA_F_TENTATIVE = 0x40
23IFA_F_PERMANENT = 0x80
24IFA_F_MANAGETEMPADDR = 0x100
25IFA_F_NOPREFIXROUTE = 0x200
26IFA_F_MCAUTOJOIN = 0x400
27IFA_F_STABLE_PRIVACY = 0x800
28
29(IFA_F_NAMES, IFA_F_VALUES) = map_namespace('IFA_F', globals())
30# 8<----------------------------------------------
31IFA_F_TEMPORARY = IFA_F_SECONDARY
32IFA_F_NAMES['IFA_F_TEMPORARY'] = IFA_F_TEMPORARY
33IFA_F_VALUES6 = IFA_F_VALUES
34IFA_F_VALUES6[IFA_F_TEMPORARY] = 'IFA_F_TEMPORARY'
35# 8<----------------------------------------------
36
37
38class ifaddrmsg(nlmsg):
39    '''
40    IP address information
41
42    C structure::
43
44        struct ifaddrmsg {
45           unsigned char ifa_family;    /* Address type */
46           unsigned char ifa_prefixlen; /* Prefixlength of address */
47           unsigned char ifa_flags;     /* Address flags */
48           unsigned char ifa_scope;     /* Address scope */
49           int           ifa_index;     /* Interface index */
50        };
51
52    '''
53    prefix = 'IFA_'
54
55    sql_constraints = {'IFA_LOCAL': "NOT NULL DEFAULT ''"}
56
57    fields = (('family', 'B'),
58              ('prefixlen', 'B'),
59              ('flags', 'B'),
60              ('scope', 'B'),
61              ('index', 'I'))
62
63    nla_map = (('IFA_UNSPEC', 'hex'),
64               ('IFA_ADDRESS', 'ipaddr'),
65               ('IFA_LOCAL', 'ipaddr'),
66               ('IFA_LABEL', 'asciiz'),
67               ('IFA_BROADCAST', 'ipaddr'),
68               ('IFA_ANYCAST', 'ipaddr'),
69               ('IFA_CACHEINFO', 'cacheinfo'),
70               ('IFA_MULTICAST', 'ipaddr'),
71               ('IFA_FLAGS', 'uint32'))
72
73    class cacheinfo(nla):
74        fields = (('ifa_preferred', 'I'),
75                  ('ifa_valid', 'I'),
76                  ('cstamp', 'I'),
77                  ('tstamp', 'I'))
78
79    @staticmethod
80    def flags2names(flags, family=socket.AF_INET):
81        if family == socket.AF_INET6:
82            ifa_f_values = IFA_F_VALUES6
83        else:
84            ifa_f_values = IFA_F_VALUES
85        ret = []
86        for f in ifa_f_values:
87            if f & flags:
88                ret.append(ifa_f_values[f])
89        return ret
90
91    @staticmethod
92    def names2flags(flags):
93        ret = 0
94        for f in flags:
95            if f[0] == '!':
96                f = f[1:]
97            else:
98                ret |= IFA_F_NAMES[f]
99        return ret
100