xref: /trafficserver/src/wccp/WccpStatic.cc (revision 079a4027)
1 /** @file
2     WCCP static data and compile time checks.
3 
4     @section license License
5 
6     Licensed to the Apache Software Foundation (ASF) under one
7     or more contributor license agreements.  See the NOTICE file
8     distributed with this work for additional information
9     regarding copyright ownership.  The ASF licenses this file
10     to you under the Apache License, Version 2.0 (the
11     "License"); you may not use this file except in compliance
12     with the License.  You may obtain a copy of the License at
13 
14     http://www.apache.org/licenses/LICENSE-2.0
15 
16     Unless required by applicable law or agreed to in writing, software
17     distributed under the License is distributed on an "AS IS" BASIS,
18     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19     See the License for the specific language governing permissions and
20     limitations under the License.
21  */
22 
23 #include "WccpLocal.h"
24 #include "WccpMeta.h"
25 #include "tscore/ink_error.h"
26 #include "tscore/ink_defs.h"
27 
28 /* Solaris considers SIOCGIFCONF obsolete and only defines it if
29  * BSD compatibility activated. */
30 #if defined(solaris)
31 #define BSD_COMP
32 #endif
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35 #include <net/if.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <stdio.h>
40 
41 namespace wccp
42 {
43 // ------------------------------------------------------
44 // Compile time checks for internal consistency.
45 
46 struct CompileTimeChecks {
47   static unsigned int const BUCKET_SIZE = sizeof(AssignInfoComp::Bucket);
48   static unsigned int const UINT8_SIZE  = sizeof(uint8_t);
49   // A compiler error for the following line means that the size of
50   // an assignment bucket is incorrect. It must be exactly 1 byte.
51   ts::TEST_IF_TRUE<BUCKET_SIZE == UINT8_SIZE> m_check_bucket_size;
52 };
53 
54 ts::Errata::Code LVL_TMP   = 1; ///< Temporary message.
55 ts::Errata::Code LVL_FATAL = 3; ///< Fatal, cannot continue.
56 ts::Errata::Code LVL_WARN  = 2; ///< Significant, should be fixed.
57 ts::Errata::Code LVL_INFO  = 1; /// Interesting, not necessarily a problem.
58 ts::Errata::Code LVL_DEBUG = 0; /// Debugging information.
59 
60 // Find a valid local IP address given an open socket.
61 uint32_t
Get_Local_Address(int s)62 Get_Local_Address(int s)
63 {
64   // If we can't find a good address in the first 255, just give up
65   // and make the user specify an address.
66   static int const N_REQ = 255;
67   ifconf conf;
68   ifreq req[N_REQ];
69   uint32_t zret;
70 
71   conf.ifc_len = sizeof(req);
72   conf.ifc_req = req;
73   if (0 == ioctl(s, SIOCGIFCONF, &conf)) {
74     int idx      = 0;
75     ifreq *ptr   = req;
76     ifreq *limit = req + (conf.ifc_len / sizeof(*req));
77     for (; idx < N_REQ && ptr < limit; ++idx, ++ptr) {
78       zret = reinterpret_cast<sockaddr_in &>(ptr->ifr_addr).sin_addr.s_addr;
79       if ((zret & 0xFF) != 0x7F)
80         return zret;
81     }
82   }
83   return INADDR_ANY; // fail
84 }
85 
86 // Cheap, can't even be used twice in the same argument list.
87 char const *
ip_addr_to_str(uint32_t addr)88 ip_addr_to_str(uint32_t addr)
89 {
90   static char buff[4 * 3 + 3 + 1];
91   unsigned char *octet = reinterpret_cast<unsigned char *>(&addr);
92   sprintf(buff, "%d.%d.%d.%d", octet[0], octet[1], octet[2], octet[3]);
93   return buff;
94 }
95 
96 // ------------------------------------------------------
97 ts::Errata &
log(ts::Errata & err,ts::Errata::Id id,ts::Errata::Code code,char const * text)98 log(ts::Errata &err, ts::Errata::Id id, ts::Errata::Code code, char const *text)
99 {
100   err.push(id, code, text);
101   return err;
102 }
103 
104 ts::Errata &
log(ts::Errata & err,ts::Errata::Code code,char const * text)105 log(ts::Errata &err, ts::Errata::Code code, char const *text)
106 {
107   err.push(0, code, text);
108   return err;
109 }
110 
111 ts::Errata
log(ts::Errata::Code code,char const * text)112 log(ts::Errata::Code code, char const *text)
113 {
114   ts::Errata err;
115   err.push(0, code, text);
116   return err;
117 }
118 
119 ts::Errata &
vlogf(ts::Errata & err,ts::Errata::Id id,ts::Errata::Code code,char const * format,va_list & rest)120 vlogf(ts::Errata &err, ts::Errata::Id id, ts::Errata::Code code, char const *format, va_list &rest)
121 {
122   static size_t const SIZE = 8192;
123   char buffer[SIZE];
124 
125   vsnprintf(buffer, SIZE, format, rest);
126   err.push(id, code, buffer);
127   return err;
128 }
129 
130 ts::Errata &
logf(ts::Errata & err,ts::Errata::Id id,ts::Errata::Code code,char const * format,...)131 logf(ts::Errata &err, ts::Errata::Id id, ts::Errata::Code code, char const *format, ...)
132 {
133   va_list rest;
134   va_start(rest, format);
135   va_end(rest);
136   return vlogf(err, id, code, format, rest);
137 }
138 
139 ts::Errata
logf(ts::Errata::Code code,char const * format,...)140 logf(ts::Errata::Code code, char const *format, ...)
141 {
142   ts::Errata err;
143   va_list rest;
144   va_start(rest, format);
145   va_end(rest);
146   return vlogf(err, ts::Errata::Id(0), code, format, rest);
147 }
148 
149 ts::Errata &
logf(ts::Errata & err,ts::Errata::Code code,char const * format,...)150 logf(ts::Errata &err, ts::Errata::Code code, char const *format, ...)
151 {
152   va_list rest;
153   va_start(rest, format);
154   va_end(rest);
155   return vlogf(err, ts::Errata::Id(0), code, format, rest);
156 }
157 
158 ts::Errata
log_errno(ts::Errata::Code code,char const * text)159 log_errno(ts::Errata::Code code, char const *text)
160 {
161   static size_t const SIZE = 1024;
162   char buffer[SIZE];
163   ATS_UNUSED_RETURN(strerror_r(errno, buffer, SIZE));
164   return logf(code, "%s [%d] %s", text, errno, buffer);
165 }
166 
167 ts::Errata
vlogf_errno(ts::Errata::Code code,char const * format,va_list & rest)168 vlogf_errno(ts::Errata::Code code, char const *format, va_list &rest)
169 {
170   int e = errno; // Preserve value before making system calls.
171   ts::Errata err;
172   static int const E_SIZE = 1024;
173   char e_buffer[E_SIZE];
174   static int const T_SIZE = 8192;
175   char t_buffer[T_SIZE];
176 
177   int n = vsnprintf(t_buffer, T_SIZE, format, rest);
178   if (0 <= n && n < T_SIZE) { // still have room.
179     ATS_UNUSED_RETURN(strerror_r(e, e_buffer, E_SIZE));
180     snprintf(t_buffer + n, T_SIZE - n, "[%d] %s", e, e_buffer);
181   }
182   err.push(ts::Errata::Id(0), code, t_buffer);
183   return err;
184 }
185 
186 ts::Errata
logf_errno(ts::Errata::Code code,char const * format,...)187 logf_errno(ts::Errata::Code code, char const *format, ...)
188 {
189   va_list rest;
190   va_start(rest, format);
191   va_end(rest);
192   return vlogf_errno(code, format, rest);
193 }
194 // ------------------------------------------------------
195 } // namespace wccp
196