231a0a8b387c83b745383590083a2f0493a4c858
[demo.git] / vnfs / vCPE / kea-sdnc-notify-mod / src / pkt4_send.cc
1 /*****************************************************************************
2 * @file
3 * main function to process ipv4 packets
4 * -------
5 *
6 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *        http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ****************************************************************************/
20
21 #include <dhcp/pkt4.h>
22 #include <log/logger.h>
23 #include <log/macros.h>
24 #include <log/message_initializer.h>
25 #include "library_common.h"
26 #include <curl/curl.h>
27 #include <sstream>
28
29 using namespace isc::dhcp;
30 using namespace isc::hooks;
31 using namespace std;
32 using namespace isc::log;
33 namespace pt = boost::property_tree;
34
35
36 isc::log::Logger logger("sdnc-notify-logger");
37 const char* log_messages[] = {
38     "SNL_BASE", "message: %1",
39     "SNL_PKT_SEND", "Outgoing packet: \n%1",
40     "SNL_CURL_RECEIVED", "Received: \n%1",
41     "SNL_CURL_FAILED", "Unable to receive data from %1",
42     NULL
43 };
44
45 /// Initializer for log messages.
46 const MessageInitializer message_initializer(log_messages);
47
48 extern "C" {
49 int pkt4_send(CalloutHandle& handle) {
50
51     // Curl variables 
52     CURL *curl;
53     CURLcode res;
54     struct curl_slist *list=NULL;
55     bool perform_updates = 0;
56     int curl_opt_res = 0;
57
58     // "C" variables.
59     char *bp;
60     size_t size;
61     FILE *response_memfile;
62
63     // String variables
64     string hwaddr;
65     string final_url;
66     string msg_name;
67     string yiaddr;
68     string post_data;
69     
70
71     // Pkt4 variables.
72     Pkt4Ptr response4_ptr;
73     HWAddrPtr hwaddr_ptr;
74     
75     // Boost / json related variables.
76     pt::ptree root;
77     std::stringstream ss;
78     boost::optional<std::string> siaddr_json_field;
79
80     /* Begin Code */
81     handle.getArgument("response4", response4_ptr);
82     hwaddr_ptr = response4_ptr->getHWAddr();
83     isc::asiolink::IOAddress new_yiaddr(response4_ptr->getYiaddr());
84     hwaddr = hwaddr_ptr->toText(false);
85     yiaddr = new_yiaddr.toText();
86     msg_name = response4_ptr->getName();
87     post_data = "{ macaddr=" + hwaddr + "&yiaddr=" + yiaddr + "&msg=" + msg_name + "}";
88     final_url = json_params[0] + hwaddr;
89     LOG_DEBUG(logger, 0, "SNL_BASE").arg(final_url);
90     LOG_DEBUG(logger, 0, "SNL_BASE").arg(yiaddr);
91
92
93     if ( msg_name == "DHCPACK")
94         perform_updates = 1;
95
96     if (!perform_updates) {
97         LOG_WARN(logger, "SNL_BASE").arg("Nothing to update.");
98         return(0);
99     }
100
101     curl_global_init(CURL_GLOBAL_DEFAULT);
102     curl = curl_easy_init();
103     if(!curl) {
104         curl_global_cleanup();
105         LOG_ERROR(logger, "SNL_BASE").arg("Could not initialize curl");
106         return(1);
107     }
108
109     list = curl_slist_append(list, "Accept: application/json");
110     if (list == NULL) {
111         curl_easy_cleanup(curl);
112         curl_global_cleanup();
113         LOG_ERROR(logger, "SNL_BASE").arg("Could not create curl slist.");
114         return(1);
115     }
116
117     response_memfile = open_memstream (&bp, &size);
118     if (response_memfile == NULL) {
119         curl_easy_cleanup(curl);
120         curl_global_cleanup();
121         LOG_ERROR(logger, "SNL_BASE").arg("Could not create memfile.");
122         return(1);
123     }
124         
125     // DEBUGGING
126     curl_opt_res += curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
127     curl_opt_res += curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
128
129     // If we don't set a timeout, curl will try for 300 seconds by default.
130     curl_opt_res += curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);
131     curl_opt_res += curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);
132     // libcurl's docs say to cast as void, don't blame me.
133     curl_opt_res += curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response_memfile);
134     // CURLOPT_URL takes a char*
135     curl_opt_res += curl_easy_setopt(curl, CURLOPT_URL, (final_url).c_str());
136     
137     // let curl use strlen
138     curl_opt_res += curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L );
139     curl_opt_res += curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data.c_str() );
140     curl_opt_res += curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
141
142     #ifdef SKIP_PEER_VERIFICATION
143     curl_opt_res += curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
144     #endif
145
146     #ifdef SKIP_HOSTNAME_VERIFICATION
147     curl_opt_res += curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
148     #endif
149     if (curl_opt_res > 0) {
150       fclose(response_memfile);
151       free(bp);
152       curl_easy_cleanup(curl);
153       curl_global_cleanup();
154       LOG_ERROR(logger, "SNL_BASE").arg("Error setting curl options.");
155       return(1);
156     }
157     res = curl_easy_perform(curl);
158     /* Check for errors */
159     if(res != CURLE_OK) {
160         fclose(response_memfile);
161         free(bp);
162         curl_easy_cleanup(curl);
163         curl_global_cleanup();
164         LOG_ERROR(logger, "SNL_CURL_FAILED").arg(ss.str());
165         return(1);
166     }
167     // make bp available for reading.
168     fclose(response_memfile);
169     curl_easy_cleanup(curl);
170     curl_global_cleanup();
171     ss << bp;
172     free(bp);
173     LOG_DEBUG(logger, 0, "SNL_CURL_RECEIVED").arg(ss.str());
174     // Load the json file in this ptree
175
176
177     LOG_DEBUG(logger, 0, "SNL_PKT_SEND").arg(response4_ptr->toText());
178
179     return(0);
180 }
181 }