1diff --git a/cups/http.h b/cups/http.h
2index 6c45301e..ac166970 100644
3--- a/cups/http.h
4+++ b/cups/http.h
5@@ -556,10 +556,11 @@ extern int		httpSetCredentials(http_t *http, cups_array_t *certs) _CUPS_API_1_5;
6 extern void		httpSetTimeout(http_t *http, double timeout, http_timeout_cb_t cb, void *user_data) _CUPS_API_1_5;
7 
8 /**** New in CUPS 1.6/macOS 10.8 ****/
9-extern http_addrlist_t	*httpAddrConnect2(http_addrlist_t *addrlist, int *sock, int msec, int *cancel) _CUPS_API_1_6;
10+extern http_addrlist_t	*httpAddrConnect2(http_addrlist_t *addrlist, int *sock, int msec, int *cancel, const char *nic) _CUPS_API_1_6;
11 extern http_state_t	httpGetState(http_t *http) _CUPS_API_1_6;
12 extern http_version_t	httpGetVersion(http_t *http) _CUPS_API_1_6;
13 extern int		httpReconnect2(http_t *http, int msec, int *cancel) _CUPS_API_1_6;
14+extern int		httpReconnect3(http_t *http, int msec, int *cancel, const char *nic) _CUPS_API_1_6;
15 
16 
17 /**** New in CUPS 1.7/macOS 10.9 ****/
18@@ -569,6 +570,7 @@ extern int		httpAddrListen(http_addr_t *addr, int port) _CUPS_API_1_7;
19 extern int		httpAddrPort(http_addr_t *addr) _CUPS_API_1_7;
20 extern char		*httpAssembleUUID(const char *server, int port, const char *name, int number, char *buffer, size_t bufsize) _CUPS_API_1_7;
21 extern http_t		*httpConnect2(const char *host, int port, http_addrlist_t *addrlist, int family, http_encryption_t encryption, int blocking, int msec, int *cancel) _CUPS_API_1_7;
22+extern http_t		*httpConnect3(const char *host, int port, http_addrlist_t *addrlist, int family, http_encryption_t encryption, int blocking, int msec, int *cancel, const char *nic) _CUPS_API_1_7;
23 extern const char	*httpGetContentEncoding(http_t *http) _CUPS_API_1_7;
24 extern http_status_t	httpGetExpect(http_t *http) _CUPS_API_1_7;
25 extern ssize_t		httpPeek(http_t *http, char *buffer, size_t length) _CUPS_API_1_7;
26diff --git a/cups/http.c b/cups/http.c
27index 66dd3b07..e98c0550 100644
28--- a/cups/http.c
29+++ b/cups/http.c
30@@ -476,6 +476,53 @@ httpConnect2(
31   return (NULL);
32 }
33 
34+/*
35+ * 'httpConnect3()' - Connect to a HTTP server.
36+ *
37+ * @since CUPS 1.7/macOS 10.9@
38+ */
39+
40+http_t *				/* O - New HTTP connection */
41+httpConnect3(
42+    const char        *host,		/* I - Host to connect to */
43+    int               port,		/* I - Port number */
44+    http_addrlist_t   *addrlist,	/* I - List of addresses or @code NULL@ to lookup */
45+    int               family,		/* I - Address family to use or @code AF_UNSPEC@ for any */
46+    http_encryption_t encryption,	/* I - Type of encryption to use */
47+    int               blocking,		/* I - 1 for blocking connection, 0 for non-blocking */
48+    int               msec,		/* I - Connection timeout in milliseconds, 0 means don't connect */
49+    int               *cancel,		/* I - Pointer to "cancel" variable */
50+    const char        *nic)
51+{
52+  http_t	*http;			/* New HTTP connection */
53+
54+
55+  DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port, (void *)addrlist, family, encryption, blocking, msec, (void *)cancel));
56+
57+ /*
58+  * Create the HTTP structure...
59+  */
60+
61+  if ((http = http_create(host, port, addrlist, family, encryption, blocking,
62+                          _HTTP_MODE_CLIENT)) == NULL)
63+    return (NULL);
64+
65+ /*
66+  * Optionally connect to the remote system...
67+  */
68+
69+  if (msec == 0 || !httpReconnect3(http, msec, cancel, nic))
70+    return (http);
71+
72+ /*
73+  * Could not connect to any known address - bail out!
74+  */
75+
76+  httpClose(http);
77+
78+  return (NULL);
79+}
80+
81 
82 /*
83  * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
84@@ -2397,7 +2444,133 @@ httpReconnect2(http_t *http,		/* I - HTTP connection */
85                   httpAddrPort(&(current->addr))));
86 #endif /* DEBUG */
87 
88-  if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec, cancel)) == NULL)
89+  if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec, cancel, NULL)) == NULL)
90+  {
91+   /*
92+    * Unable to connect...
93+    */
94+
95+#ifdef _WIN32
96+    http->error  = WSAGetLastError();
97+#else
98+    http->error  = errno;
99+#endif /* _WIN32 */
100+    http->status = HTTP_STATUS_ERROR;
101+
102+    DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s",
103+                  strerror(http->error)));
104+
105+    return (-1);
106+  }
107+
108+  DEBUG_printf(("2httpReconnect2: New socket=%d", http->fd));
109+
110+  if (http->timeout_value > 0)
111+    http_set_timeout(http->fd, http->timeout_value);
112+
113+  http->hostaddr = &(addr->addr);
114+  http->error    = 0;
115+
116+#ifdef HAVE_TLS
117+  if (http->encryption == HTTP_ENCRYPTION_ALWAYS)
118+  {
119+   /*
120+    * Always do encryption via SSL.
121+    */
122+
123+    if (_httpTLSStart(http) != 0)
124+    {
125+      httpAddrClose(NULL, http->fd);
126+      http->fd = -1;
127+
128+      return (-1);
129+    }
130+  }
131+  else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls_upgrade)
132+    return (http_tls_upgrade(http));
133+#endif /* HAVE_TLS */
134+
135+  DEBUG_printf(("1httpReconnect2: Connected to %s:%d...",
136+		httpAddrString(http->hostaddr, temp, sizeof(temp)),
137+		httpAddrPort(http->hostaddr)));
138+
139+  return (0);
140+}
141+
142+/*
143+ * 'httpReconnect3()' - Reconnect to a HTTP server with timeout and optional
144+ *                      cancel.
145+ */
146+
147+int					/* O - 0 on success, non-zero on failure */
148+httpReconnect3(http_t *http,		/* I - HTTP connection */
149+	       int    msec,		/* I - Timeout in milliseconds */
150+	       int    *cancel,		/* I - Pointer to "cancel" variable */
151+         const char *nic)
152+{
153+  http_addrlist_t	*addr;		/* Connected address */
154+#ifdef DEBUG
155+  http_addrlist_t	*current;	/* Current address */
156+  char			temp[256];	/* Temporary address string */
157+#endif /* DEBUG */
158+
159+
160+  DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", (void *)http, msec, (void *)cancel));
161+
162+  if (!http)
163+  {
164+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
165+    return (-1);
166+  }
167+
168+#ifdef HAVE_TLS
169+  if (http->tls)
170+  {
171+    DEBUG_puts("2httpReconnect2: Shutting down SSL/TLS...");
172+    _httpTLSStop(http);
173+  }
174+#endif /* HAVE_TLS */
175+
176+ /*
177+  * Close any previously open socket...
178+  */
179+
180+  if (http->fd >= 0)
181+  {
182+    DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd));
183+
184+    httpAddrClose(NULL, http->fd);
185+
186+    http->fd = -1;
187+  }
188+
189+ /*
190+  * Reset all state (except fields, which may be reused)...
191+  */
192+
193+  http->state           = HTTP_STATE_WAITING;
194+  http->version         = HTTP_VERSION_1_1;
195+  http->keep_alive      = HTTP_KEEPALIVE_OFF;
196+  memset(&http->_hostaddr, 0, sizeof(http->_hostaddr));
197+  http->data_encoding   = HTTP_ENCODING_FIELDS;
198+  http->_data_remaining = 0;
199+  http->used            = 0;
200+  http->data_remaining  = 0;
201+  http->hostaddr        = NULL;
202+  http->wused           = 0;
203+
204+ /*
205+  * Connect to the server...
206+  */
207+
208+#ifdef DEBUG
209+  for (current = http->addrlist; current; current = current->next)
210+    DEBUG_printf(("2httpReconnect2: Address %s:%d",
211+                  httpAddrString(&(current->addr), temp, sizeof(temp)),
212+                  httpAddrPort(&(current->addr))));
213+#endif /* DEBUG */
214+
215+  if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec, cancel, NULL)) == NULL)
216   {
217    /*
218     * Unable to connect...
219diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c
220index 6e73464c..36b410e8 100644
221--- a/cups/http-addrlist.c
222+++ b/cups/http-addrlist.c
223@@ -39,7 +39,7 @@ httpAddrConnect(
224 {
225   DEBUG_printf(("httpAddrConnect(addrlist=%p, sock=%p)", (void *)addrlist, (void *)sock));
226 
227-  return (httpAddrConnect2(addrlist, sock, 30000, NULL));
228+  return (httpAddrConnect2(addrlist, sock, 30000, NULL, NULL));
229 }
230 
231 
232@@ -55,7 +55,8 @@ httpAddrConnect2(
233     http_addrlist_t *addrlist,		/* I - List of potential addresses */
234     int             *sock,		/* O - Socket */
235     int             msec,		/* I - Timeout in milliseconds */
236-    int             *cancel)		/* I - Pointer to "cancel" variable */
237+    int             *cancel,		/* I - Pointer to "cancel" variable */
238+    const char      *nic)
239 {
240   int			val;		/* Socket option value */
241 #ifndef _WIN32
242@@ -164,6 +165,11 @@ httpAddrConnect2(
243       setsockopt(fds[nfds], SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
244 #endif /* SO_NOSIGPIPE */
245 
246+      if (nic != NULL) {
247+        val = 1;
248+        setsockopt(fds[nfds], SOL_SOCKET, SO_BINDTODEVICE, nic, sizeof(nic));
249+      }
250+
251      /*
252       * Using TCP_NODELAY improves responsiveness, especially on systems
253       * with a slow loopback interface...
254diff --git a/backend/ipp.c b/backend/ipp.c
255index c4b34668..60b867a0 100644
256--- a/backend/ipp.c
257+++ b/backend/ipp.c
258@@ -64,6 +64,7 @@ typedef struct _cups_monitor_s		/**** Monitoring data ****/
259   ipp_jstate_t		job_state;	/* Current job state */
260   ipp_pstate_t		printer_state;	/* Current printer state */
261   int			retryable;	/* Is this a job that should be retried? */
262+  const char *nic;
263 } _cups_monitor_t;
264 
265 
266@@ -273,6 +274,7 @@ main(int  argc,				/* I - Number of command-line args */
267   ppd_file_t	*ppd = NULL;		/* PPD file */
268   _ppd_cache_t	*pc = NULL;		/* PPD cache and mapping data */
269   fd_set	input;			/* Input set for select() */
270+  const char *nic = NULL;
271 
272 
273  /*
274@@ -651,6 +653,10 @@ main(int  argc,				/* I - Number of command-line args */
275     password = getenv("AUTH_PASSWORD");
276   }
277 
278+  num_options = cupsParseOptions(argv[5], 0, &options);
279+  nic = cupsGetOption("nic", num_options, options);
280+  fprintf(stderr, "DEBUG: nic %s\n", nic);
281+
282  /*
283   * Try finding the remote server...
284   */
285@@ -659,8 +665,11 @@ main(int  argc,				/* I - Number of command-line args */
286 
287   addrlist = backendLookup(hostname, port, &job_canceled);
288 
289-  http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
290-                      0, NULL);
291+  if (nic != NULL) {
292+    http = httpConnect3(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1, 0, NULL, nic);
293+  } else {
294+    http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1, 0, NULL);
295+  }
296   httpSetTimeout(http, 30.0, timeout_cb, NULL);
297 
298  /*
299@@ -701,7 +710,7 @@ main(int  argc,				/* I - Number of command-line args */
300     fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
301     _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
302 
303-    if (httpReconnect2(http, 30000, NULL))
304+    if (nic != NULL ? httpReconnect3(http, 30000, NULL, nic) : httpReconnect2(http, 30000, NULL))
305     {
306       int error = errno;		/* Connection error */
307 
308@@ -986,7 +995,7 @@ main(int  argc,				/* I - Number of command-line args */
309 	  version = 10;
310         }
311 
312-	httpReconnect2(http, 30000, NULL);
313+	nic != NULL ? httpReconnect3(http, 30000, NULL, nic) : httpReconnect2(http, 30000, NULL);
314       }
315       else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
316       {
317@@ -1018,7 +1027,7 @@ main(int  argc,				/* I - Number of command-line args */
318 	                     _("Unable to get printer status."));
319         sleep(10);
320 
321-	httpReconnect2(http, 30000, NULL);
322+	nic != NULL ? httpReconnect3(http, 30000, NULL, nic) : httpReconnect2(http, 30000, NULL);
323       }
324 
325       ippDelete(supported);
326@@ -1450,6 +1459,7 @@ main(int  argc,				/* I - Number of command-line args */
327   monitor.job_state     = IPP_JSTATE_PENDING;
328   monitor.printer_state = IPP_PSTATE_IDLE;
329   monitor.retryable     = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
330+  monitor.nic           = nic;
331 
332   fprintf(stderr, "DEBUG: retryable=%d\n", monitor.retryable);
333 
334@@ -2063,7 +2073,7 @@ main(int  argc,				/* I - Number of command-line args */
335       * Do the request...
336       */
337 
338-      httpReconnect2(http, 30000, NULL);
339+      nic != NULL ? httpReconnect3(http, 30000, NULL, nic) : httpReconnect2(http, 30000, NULL);
340       response   = cupsDoRequest(http, request, resource);
341       ipp_status = cupsLastError();
342 
343@@ -2457,8 +2467,13 @@ monitor_printer(
344   * Make a copy of the printer connection...
345   */
346 
347-  http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
348-                      monitor->encryption, 1, 0, NULL);
349+  if (monitor->nic != NULL) {
350+    http = httpConnect3(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
351+                        monitor->encryption, 1, 0, NULL, monitor->nic);
352+  } else {
353+    http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
354+                        monitor->encryption, 1, 0, NULL);
355+  }
356   httpSetTimeout(http, 30.0, timeout_cb, NULL);
357   if (username[0])
358     cupsSetUser(username);
359@@ -2480,7 +2495,7 @@ monitor_printer(
360     */
361 
362     if (httpGetFd(http) < 0)
363-      httpReconnect2(http, 30000, NULL);
364+      monitor->nic != NULL ? httpReconnect3(http, 30000, NULL, monitor->nic) : httpReconnect2(http, 30000, NULL);
365 
366     if (httpGetFd(http) >= 0)
367     {
368@@ -2702,7 +2717,7 @@ monitor_printer(
369   if (job_canceled > 0 && monitor->job_id > 0)
370   {
371     if (httpGetFd(http) < 0)
372-      httpReconnect2(http, 30000, NULL);
373+      monitor->nic != NULL ? httpReconnect3(http, 30000, NULL, monitor->nic) : httpReconnect2(http, 30000, NULL);
374 
375     if (httpGetFd(http) >= 0)
376     {
377diff --git a/tools/ippeveprinter.c b/tools/ippeveprinter.c
378index 2da5ed52..39274b6f 100644
379--- a/tools/ippeveprinter.c
380+++ b/tools/ippeveprinter.c
381@@ -6842,7 +6842,7 @@ process_job(ippeve_job_t *job)		/* I - Job */
382 
383         if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
384           fprintf(stderr, "[Job %d] Unable to find \"%s\": %s\n", job->id, host, cupsLastErrorString());
385-        else if (!httpAddrConnect2(addrlist, &mystdout, 30000, &(job->cancel)))
386+        else if (!httpAddrConnect2(addrlist, &mystdout, 30000, &(job->cancel), NULL))
387           fprintf(stderr, "[Job %d] Unable to connect to \"%s\": %s\n", job->id, host, cupsLastErrorString());
388 
389         httpAddrFreeList(addrlist);
390